Skip to content

MSc

Bitcoin Address Clustering

Collapsing 334,177 Bitcoin addresses into 109,074 entities over the chain's first two years, using a heuristic chain tuned to avoid merging entities that are not the same one.

Jun 2022BitcoinMeasurementPrivacy

Bitcoin addresses are pseudonymous individually and leaky in aggregate: the way transactions are constructed reveals which addresses are controlled by the same entity. This builds the transaction graph for the chain’s first 115,000 blocks and applies a chain of ownership heuristics to it.

Scope
Blocks 0–115,000, January 2009 to February 2011
Data
blockchain.info block API
Graph
559,528 nodes · 630,301 edges
Explorer
Streamlit + PyVis, local
Repository
VincenzoImp/bitcoin-address-clustering
VincenzoImp/bitcoin-address-clusteringBitcoin address clustering using multiple ownership heuristics over the transaction graph.Jupyter Notebook

The problem

Common-input-ownership – if two addresses fund the same transaction, one entity controls both – is the heuristic everybody quotes, and on its own it recovers very little. The rest of the signal is in change addresses: a payment usually has two outputs, one to the recipient and one back to the sender, and deciding which is which is where the real inference happens.

Every one of those inferences can be wrong, and the errors do not stay local. Merging two entities that are not the same entity does not produce one bad row; it welds two subgraphs together and corrupts every conclusion downstream.

What I built

The graph is transaction-centric: transactions are nodes, UTXOs are edges carrying the address and value, with synthetic nodes for coinbase and unspent outputs. It is assembled from the blockchain.info block API rather than from a node, with Spark handling the extraction and aggregation and the clustering itself running as a two-pass sweep in temporal order.

334,177

addresses

109,074

entities after clustering

67.4%

reduction

The heuristics are a chain, not a single rule: coinbase outputs grouped per miner, a special case for early Satoshi-era blocks, consolidation transactions, common-input-ownership on payments, and a family of five change-address tests tried in order: the same address appearing in input and output, unnecessary inputs, an output address never seen before, round-number amounts, and address reuse. Transactions that look like CoinJoins are detected and excluded from the heuristics, with a single round of taint analysis run instead.

A Streamlit app with a PyVis rendering lets you pick an entity and see its subgraph.

Hard parts

Choosing precision and paying for it. The notebook states the design position directly: the algorithm aims to reduce false positives as much as possible, avoiding the merge of two addresses belonging to different entities. The cost is written in the results: most clusters end up holding one or two addresses, which is why a second, weaker pass exists that discards singletons and takes the count from 109,074 down to 14,933. That second number is more useful and less defensible, and the notebook keeps them separate rather than reporting one.

Knowing when not to apply a heuristic. A CoinJoin deliberately violates common-input ownership. Running the heuristics over one does not fail: it confidently merges unrelated people. Detecting the pattern and stepping back from it is the only correct response, and it means accepting that those transactions stay unresolved.