Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

decluster

Evidence-weighted de-anonymization of Bitcoin transactions. It reads how each transaction was built (wallet fingerprints) and how its amounts partition (subtransaction structure), scores every signal as bits of evidence, and clusters coins by owner.

Two coins spent in the same transaction are normally assumed to share an owner. Because the evidence here is signed, the clustering can instead keep them apart when their fingerprints and amounts say they belong to different owners — undoing the false link a collaborative transaction deliberately plants (its whole purpose is to make an analyst merge two people into one).

  • Fingerprints reveal which wallet built a transaction. Every wallet leaves quirks in how it constructs a transaction — nSequence values, script types, signature grinding, and more. Do those quirks actually identify the wallet? Taking address reuse as the same-owner label (two transactions spending the same address are the same wallet), the measured fingerprint bits rank a same-wallet pair of transactions above a random pair 93.3% of the time (AUC 0.933) on 166k real mainnet transactions. Shuffle the labels and it drops to 0.50 (a coin flip) — so the 0.933 is real signal, not an artifact.

  • The shape of the payment graph reveals owners too. Independently of who-spent-with-whom, the structure of the graph (who pays whom) betrays common ownership — the same effect that de-anonymized social networks (Narayanan–Shmatikov). Across five eras (2012–2024), payment-graph structure alone predicts whether two addresses share an owner, ranking same-owner pairs correctly 0.95–0.97 of the time at one hop on the clean eras, and 0.97–1.00 across all five eras by four hops (1.0 = perfect, 0.5 = chance; the churny 2013 slice starts near chance at one hop and needs the deeper hops).

  • It survives a transaction built to fool it. On a real transaction deliberately constructed to merge two owners into one (the false link from above), the method keeps them apart: the amount structure alone re-partitions them into the correct two owners, and the fingerprints independently agree — recovering the answer that a merge-only clustering gets wrong.

Layout

  • decluster/ — the attacker (the measurement half that runs): extractors, library, combiner, cluster (engine: cluster_refined), propagate (entity-level N-S seed-and-propagate via provenance signatures; synthetic evaluation), graph_deanon
  • the construction/cost half (deferred — PAPER §9): cost (leak / amount-cut / topology leaf terms + the deferred construction_cost), ancestry (the absorber-model provenance target; feeds propagate), report (fuses the terms on a real tx), subsetsum/coinjoin_demix (the amount de-mix channel); consumes the dense-subset-sum engine (build: maturin develop); cluster_refined optionally refuses links when provenance and fingerprints diverge
  • chain-analysis channels that select what to ask and read the answer, all outside the engine: conservation (what the other participants could not have funded — arithmetic on one transaction, no client model), provenance (which inputs descend from known transactions), monitor (watches tracked coins for the co-spend an intersection argument needs), intersect (the N-ary origin intersection, handed to cluster_refined to score rather than asserted)
  • PAPER.md — the manuscript; results/ — reproducible outputs; catalog/, bigquery/

Installable (pip install -e .), so a protocol-specific client model can consume these primitives from above without this repository knowing the protocol exists.

Every number is reproducible. MIT — see LICENSE.

About

Evidence-weighted de-anonymization of Bitcoin transactions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages