Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Bitcoin is pseudonymous, not anonymous. Every transaction is public; chain analysis firms cluster addresses into wallets, link wallets to exchanges, and trace flows. Understanding what is and isn't private — and the modern tools that improve privacy (CoinJoin, Lightning, silent payments, Taproot) — is essential for any builder shipping consumer Bitcoin software.
Address clustering.
# Chain-analysis firms cluster addresses with these heuristics:
# 1. Common-input ownership heuristic (CIOH):
# If two addresses appear as inputs in the same tx, they're likely owned
# by the same wallet (because spending requires the corresponding private key).
# 2. Change-output heuristic:
# Identify which output is change vs payment.
# Often the change output is the "round number off" one, e.g., 0.5 BTC payment + 0.32847291 change.
# 3. Reuse heuristic:
# Reused addresses are bound to a single owner over time.
# Counter-strategies:
# - CoinJoin: many users combine inputs in one tx, breaking CIOH
# - Avoid address reuse: each receive uses a new address (BIP-32 HD wallets)
# - Lightning: tx is off-chain; only open/close hits the chain
# - Silent payments (BIP-352): static reusable address; receiver-derived per-tx address
# Example clustering pseudocode:
clusters = {} # addr -> cluster_id
next_cluster_id = 0
def add_tx(tx):
global next_cluster_id
if len(tx.inputs) > 1:
in_addrs = [tx.input_addr(i) for i in tx.inputs]
# Find existing cluster for any input addr, or create new
existing = next((clusters.get(a) for a in in_addrs if a in clusters), None)
if existing is None:
existing = next_cluster_id
next_cluster_id += 1
# Merge all input addrs into existing cluster
for a in in_addrs:
clusters[a] = existing
# Heuristic: identify change output (smallest output is often change for round payments)
# ... etc
# Real implementations: BlockSci, WalletExplorer, Chainalysis Reactor, Elliptic