Cryptocurrency Mixing
Privacy implementations withJoinMarket for Bitcoin
and Masternode mixing for Dash
ContentsA normal transactionWhat is the problem for privacy?How does CoinJoin help?JoinMarket: peer-to-peer CoinJoin for BitcoinMasternode mixing: ahead-of-time mixing for DashSummary
Transactions
Example transactions
10 BTC 7 BTC
3 BTCsignatur
e
input output
output
3 BTC 4 BTC
1 BTCsignatur
e
input output
output2 BTC
signature
input
Example real transaction
signature
public key
Typical “send money” case
10 BTC 7 BTC
3 BTCsignatur
e
change returned to sender
money drawnfrom wallet
money sentto recipient
What does Bob knowabout Alice’s finances?
Multiple inputs
a: 6 BTC 7 BTC
3 BTC
signature
change returned to sender
money drawnfrom wallet
money sentto recipient
b: 4 BTCsignature
How much extra informationdoes this reveal to Bob?
Address reuse10 BTC 7 BTC
3 BTCsignatur
e
3 BTC 4 BTC
1 BTC
signature
1abcxyz…
What does this reveal about Alice and Dorothy?
3 BTCsignature
CoinJoin
Disjunct transactions
10 BTC 7 BTC
3 BTCsignatur
e
input output
output
3 BTC 4 BTC
1 BTCsignatur
e
input output
output2 BTC
signature
Even they are made by different people, do they need to be separate on the blockchain?
Joined transactions10 BTC 7 BTC
3 BTCsignatur
e
input output
output
3 BTC 4 BTC
1 BTCsignatur
e
input output
output2 BTC
signature
input
Is it possible to correlate the inputs with the outputs?
JoinMarket
JoinMarket actorsInvestor with
spare bitcoins and timeBitcoin user who wants
extra privacy
“taker”“maker”
JoinMarket principleIvan the Investor
How do we get people like Ivan to keep his coins in a wallet for mixing?
taker fee
Network topologyIRC server
(trading pit)
Tor network
mixing peer mixing peermixing peer
(future versions of JoinMarket may replace
IRC with P2Pcommunication)
CoinJoin communication
maker
taker
maker
runningyieldgenerator.py
runningyieldgenerator.py
private messages
runningsendpayment.py
public messages
orderorderbook
orderbookfillpubkeyioauthauth
txsig
(etc…)
Sample Transaction
3 parties, amount 25 BTC
How does it look?
Installation% git clone \ https://github.com/JoinMarket-Org/joinmarket.git \ joinmarket-btcmcr1% cd joinmarket-btcmcr1
Wallet generation
% python wallet-tool.py generate
2016-05-01 18:50:04,176 [MainThread ] [DEBUG] hello joinmarketWrite down this wallet recovery seed
warm shade knee satisfy child bone hug door leaf depress blur use
Enter wallet encryption passphrase: Reenter wallet encryption passphrase: Input wallet file name (default: wallet.json): saved to wallet.json
generate command
wallet seed
wallet filename
Switch to Bitcoin full node
see local Bitcoin Core/Classic etc data folder
Switch toBitcoin full node
display walletcommand% python wallet-tool.py wallet.json
2016-05-01 18:58:49,303 [MainThread ] [DEBUG] hello joinmarketEnter wallet decryption passphrase: 2016-05-01 18:58:50,722 [MainThread ] [DEBUG] requesting wallet history2016-05-01 18:58:54,491 [MainThread ] [DEBUG] rpc: getaddressesbyaccount ['joinmarket-wallet-9e5123']2016-05-01 18:58:54,496 [MainThread ] [DEBUG] importing 200 addresses into account joinmarket-wallet-9e5123restart Bitcoin Core with -rescan if you're recovering an existing wallet from backup seed otherwise just restart this joinmarket script
importing into a local watch-only wallet(local Bitcoin node has only public keys, not private keys)
Show wallet contents
display wallet command% python wallet-tool.py wallet.json2016-05-01 19:23:41,613 [MainThread ] [DEBUG] hello joinmarketEnter wallet decryption passphrase: 2016-05-01 19:23:43,774 [MainThread ] [DEBUG] requesting wallet history2016-05-01 19:23:47,478 [MainThread ] [DEBUG] rpc: getaddressesbyaccount ['joinmarket-wallet-9e5123']2016-05-01 19:23:47,484 [MainThread ] [DEBUG] rpc: listtransactions ['joinmarket-wallet-9e5123', 1000, 0, True]2016-05-01 19:23:51,193 [MainThread ] [DEBUG] rpc: listunspent [0]2016-05-01 19:23:51,200 [MainThread ] [DEBUG] bitcoind sync_unspent took 0.00770592689514secmixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/000 14hzgMvxf9GhPTWjBxA7MHd8ytGT9dsp7n new 0.00000000 btc m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa new 0.00000000 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa new 0.00000000 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc internal addresses m/0/0/1/for mixdepth=0 balance=0.00000000btcmixing depth 1 m/0/1/ external addresses m/0/1/0/ m/0/1/0/000 19UBkuXV3kUFwdjkUyW6btL76NQSHNxoKP new 0.00000000 btc m/0/1/0/001 17bSF43rrcK6stgAXbbEEwBQJMSMh2pMhX new 0.00000000 btc …
1st internal wallet
2st internal wallet, etc
Fund wallet (anyhow)
output sent to JoinMarket wallet
% python wallet-tool.py wallet.json2016-05-01 19:52:16,028 [MainThread ] [DEBUG] hello joinmarket…mixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/000 14hzgMvxf9GhPTWjBxA7MHd8ytGT9dsp7n used 0.10000000 btc m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa new 0.00000000 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa new 0.00000000 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc m/0/0/0/006 184EYAbYveTYYLNW1ewTFV4ysEqpAswvN4 new 0.00000000 btc internal addresses m/0/0/1/for mixdepth=0 balance=0.10000000btcmixing depth 1 m/0/1/ external addresses m/0/1/0/ m/0/1/0/000 19UBkuXV3kUFwdjkUyW6btL76NQSHNxoKP new 0.00000000 btc m/0/1/0/001 17bSF43rrcK6stgAXbbEEwBQJMSMh2pMhX new 0.00000000 btc
Check funds received
1st internal wallet
% python sendpayment.py wallet.json -N 5 -m 0 2500000 19UBkuXV3kUFwdjkUyW6btL76NQSHNxoKP2016-05-01 22:41:48,340 [MainThread ] [DEBUG] hello joinmarketGenerated random nickname: Supixaxal2016-05-01 22:41:48,415 [MainThread ] [DEBUG] starting sendpaymentEnter wallet decryption passphrase: 2016-05-01 22:41:52,519 [MainThread ] [DEBUG] requesting wallet history2016-05-01 22:41:53,273 [MainThread ] [DEBUG] rpc: getaddressesbyaccount ['joinmarket-wallet-9e5123']2016-05-01 22:41:53,279 [MainThread ] [DEBUG] rpc: listtransactions ['joinmarket-wallet-9e5123', 1000, 0, True]2016-05-01 22:41:54,070 [MainThread ] [DEBUG] rpc: listunspent []2016-05-01 22:41:54,078 [MainThread ] [DEBUG] bitcoind sync_unspent took 0.00794100761414sec2016-05-01 22:41:54,083 [MainThread ] [DEBUG] starting irc2016-05-01 22:41:54,083 [Thread-1 ] [DEBUG] starting ping thread2016-05-01 22:41:54,084 [Thread-2 ] [DEBUG] starting throttle thread2016-05-01 22:41:54,084 [MainThread ] [DEBUG] connecting2016-05-01 22:41:57,173 [MainThread ] [DEBUG] Connected to IRC and joined channel2016-05-01 22:41:57,174 [MainThread ] [DEBUG] >>pubmsg !orderbookwaiting for all orders to certainly arrive…2016-05-01 22:42:50,535 [MainThread ] [DEBUG] created fully signed tx, ending2016-05-01 22:42:50,574 [MainThread ] [DEBUG] line was zero length2016-05-01 22:42:50,575 [MainThread ] [DEBUG] disconnected irc2016-05-01 22:42:50,575 [MainThread ] [DEBUG] ending irc
Send fundssend payment
command
join themarket
broadcast
Check join
% python wallet-tool.py wallet.json2016-05-01 22:50:20,154 [MainThread ] [DEBUG] hello joinmarketEnter wallet decryption passphrase: 2016-05-01 22:50:22,238 [MainThread ] [DEBUG] requesting wallet history2016-05-01 22:50:26,245 [MainThread ] [DEBUG] rpc: getaddressesbyaccount ['joinmarket-wallet-9e5123']2016-05-01 22:50:26,251 [MainThread ] [DEBUG] rpc: listtransactions ['joinmarket-wallet-9e5123', 1000, 0, True]2016-05-01 22:50:30,130 [MainThread ] [DEBUG] rpc: listunspent [0]2016-05-01 22:50:30,137 [MainThread ] [DEBUG] bitcoind sync_unspent took 0.00749111175537secmixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa new 0.00000000 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa new 0.00000000 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc m/0/0/0/006 184EYAbYveTYYLNW1ewTFV4ysEqpAswvN4 new 0.00000000 btc internal addresses m/0/0/1/ m/0/0/1/000 19DZ1jXweJtmBNn7UUPdJU2G2A8cuDCQ5y used 0.07448981 btc for mixdepth=0 balance=0.07448981btcmixing depth 1 m/0/1/ external addresses m/0/1/0/ m/0/1/0/000 19UBkuXV3kUFwdjkUyW6btL76NQSHNxoKP used 0.02500000 btc m/0/1/0/001 17bSF43rrcK6stgAXbbEEwBQJMSMh2pMhX new 0.00000000 btc
Compare mixing depths
1st internal wallet
2nd internal wallet
% python sendpayment.py wallet.json -N 5 -m 1 0 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa 2016-05-01 22:54:38,682 [MainThread ] [DEBUG] hello joinmarketGenerated random nickname: Moxivexoh2016-05-01 22:54:38,759 [MainThread ] [DEBUG] starting sendpayment…
% python wallet-tool.py wallet.json…mixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa used 0.02411938 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa new 0.00000000 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc m/0/0/0/006 184EYAbYveTYYLNW1ewTFV4ysEqpAswvN4 new 0.00000000 btc m/0/0/0/007 14jmzkDjF2Ruyn3kQwYsaS2quorjyqsZ72 new 0.00000000 btc internal addresses m/0/0/1/ m/0/0/1/000 19DZ1jXweJtmBNn7UUPdJU2G2A8cuDCQ5y used 0.07448981 btc for mixdepth=0 balance=0.09860919btcmixing depth 1 m/0/1/ external addresses m/0/1/0/ m/0/1/0/001 17bSF43rrcK6stgAXbbEEwBQJMSMh2pMhX new 0.00000000 btc m/0/1/0/002 1Hi5j3iyjUmGstQq5tLYjMTKNoVvZ5czCB new 0.00000000 btc m/0/1/0/003 19VZdjKBPXTzcWqsfLpjzPs1do1KWcPncK new 0.00000000 btc m/0/1/0/004 1FFRrzqMZbdDxdX75p7UrjY9crLi1bzGEb new 0.00000000 btc m/0/1/0/005 1BSJ5Y77hBwRwKSwZXKnDBWZF3WikC3PNo new 0.00000000 btc m/0/1/0/006 18x4KsBcUQnrGccVHvHWSRb8gco8nKUyja new 0.00000000 btc internal addresses m/0/1/1/for mixdepth=1 balance=0.00000000btc
Empty a mixing depth
amount = 0
new totalbalance
Tumbling
Generate receive addresses
generate multiple addresses for enhanced privacy
% python wallet-tool.py wallet.json2016-05-02 16:16:38,556 [MainThread ] [DEBUG] hello joinmarketEnter wallet decryption passphrase: …mixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa used 0.02411938 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa used 0.05054509 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc m/0/0/0/006 184EYAbYveTYYLNW1ewTFV4ysEqpAswvN4 new 0.00000000 btc m/0/0/0/007 14jmzkDjF2Ruyn3kQwYsaS2quorjyqsZ72 new 0.00000000 btc m/0/0/0/008 1XDsccCJLDGsW9VvzaFT2kjS332wJnqwr new 0.00000000 btc internal addresses m/0/0/1/ m/0/0/1/001 1P1ZXH2KZWBnWmfxepbf4rVtui9ZYBYgE used 0.02309129 btc for mixdepth=0 balance=0.09775576btc
Check mixing depth 0
Coins Iprepared
earlier
We will be tumbling this much
% python tumbler.py wallet.json --timelambda=1 13hGdJFTFaSaD8eJ4rXQ2yL12gVEa7LHZM 1Ck161xjSdDHwdauh7BA9ePRtx3VVzdpVg 1GEn4mdF77EULNLzoE27Eo6mpwmr8xGNEn2016-05-02 16:20:24,266 [MainThread ] [DEBUG] hello joinmarket['13hGdJFTFaSaD8eJ4rXQ2yL12gVEa7LHZM', '1Ck161xjSdDHwdauh7BA9ePRtx3VVzdpVg', '1GEn4mdF77EULNLzoE27Eo6mpwmr8xGNEn']{'liquiditywait': 60, 'addrcount': 3, 'minmakercount': 2, 'amountpower': 100.0, 'txcountparams': (4, 1), 'mixdepthcount': 4, 'waittime': 20, 'txfee': 5000, 'mincjamount': 100000, 'mixdepthsrc': 0, 'makercountrange': (3, 1.5), 'maxcjfee': (0.01, 10000), 'donateamount': 0, 'timelambda': 1.0, 'mintxcount': 1}2016-05-02 16:20:24,305 [MainThread ] [DEBUG] tumbler transaction list…TBC
Start tumbletumble commandoption to use average wait time
of 1 minute instead of 30
outputs
2016-05-02 16:20:24,305 [MainThread ] [DEBUG] tumbler transaction list[{'srcmixdepth': 0, 'tx': [{'amount_fraction': 0.26377219630602206, 'destination': 'internal', 'makercount': 2, 'wait': 0.77}, {'amount_fraction': 0.736227803693978, 'destination': 'internal', 'makercount': 2, 'wait': 0.04}]}, {'srcmixdepth': 1, 'tx': [{'amount_fraction': 0.12876737962157553, 'destination': 'internal', 'makercount': 2, 'wait': 2.36}, {'amount_fraction': 0.10885260611117395, 'destination': 'internal', 'makercount': 2, 'wait': 3.95}, {'amount_fraction': 0.7623800142672505, 'destination': '1GEn4mdF77EULNLzoE27Eo6mpwmr8xGNEn', 'makercount': 2, 'wait': 0.16}]}, {'srcmixdepth': 2, 'tx': [{'amount_fraction': 0.5982821353871555, 'destination': 'internal', 'makercount': 2, 'wait': 0.28}, {'amount_fraction': 0.40171786461284453, 'destination': '1Ck161xjSdDHwdauh7BA9ePRtx3VVzdpVg', 'makercount': 2, 'wait': 0.89}]}, {'srcmixdepth': 3, 'tx': [{'amount_fraction': 1.0, 'destination': '13hGdJFTFaSaD8eJ4rXQ2yL12gVEa7LHZM', 'makercount': 3, 'wait': 0.18}]}]waits in total for 8 blocks and 8.63 minutesestimated time taken 88.63 minutes or 1.48 hourstumble with these tx? (y/n):y…
split of funds into next round
outputs
Collect coins
technical error:tumbling stalled before I could finish the presentation
% python wallet-tool.py wallet.json…mixing depth 0 m/0/0/ external addresses m/0/0/0/ m/0/0/0/001 14QNhbnkBC6HQJgfgBP2hRDo57Ct7pKNMa used 0.02411938 btc m/0/0/0/002 1AgtMNiGVHS6oVisDbQT8VVhv9xC31QeUa used 0.05054509 btc m/0/0/0/003 12wtzHevXDxzi5eUqYja4cFCT9CA7msqDL new 0.00000000 btc m/0/0/0/004 1HPzdoUDVXyPs2Awr4VFGncvc8qL3pF5jv new 0.00000000 btc m/0/0/0/005 1KVr1QjiUsTPCyQhaGNth8BZwYaBydPTpp new 0.00000000 btc m/0/0/0/006 184EYAbYveTYYLNW1ewTFV4ysEqpAswvN4 new 0.00000000 btc m/0/0/0/007 14jmzkDjF2Ruyn3kQwYsaS2quorjyqsZ72 new 0.00000000 btc m/0/0/0/008 1XDsccCJLDGsW9VvzaFT2kjS332wJnqwr new 0.00000000 btc internal addresses m/0/0/1/ m/0/0/1/002 1Ei1yo2VDHQnHGUoaUZrJ7uWNovZU6cqg9 used 0.01039038 btc for mixdepth=0 balance=0.08505485btcmixing depth 1 m/0/1/ external addresses m/0/1/0/ m/0/1/0/001 17bSF43rrcK6stgAXbbEEwBQJMSMh2pMhX new 0.00000000 btc m/0/1/0/002 1Hi5j3iyjUmGstQq5tLYjMTKNoVvZ5czCB new 0.00000000 btc m/0/1/0/003 19VZdjKBPXTzcWqsfLpjzPs1do1KWcPncK new 0.00000000 btc m/0/1/0/004 1FFRrzqMZbdDxdX75p7UrjY9crLi1bzGEb new 0.00000000 btc m/0/1/0/005 1BSJ5Y77hBwRwKSwZXKnDBWZF3WikC3PNo new 0.00000000 btc m/0/1/0/006 18x4KsBcUQnrGccVHvHWSRb8gco8nKUyja new 0.00000000 btc internal addresses m/0/1/1/ m/0/1/1/001 15tt2crkHQsVKWBfXJoufZND626HgzrDKW used 0.01245286 btc for mixdepth=1 balance=0.01245286btc
Masternode Mixing
What is Dash?Fork of Bitcoin
Launched 18 January 2014Initially named XCoin, then Darkcoin, then Dash (“digital cash”) Initial goal was to add privacy features to Bitcoin
Current blockchain approx size: 2GBCurrent valuation:
40-50m USD market cap (compare Bitcoin 6-7bn USD)6 400 000 Dash @ 6-7USD (compare Bitcoin 15 500 000 coins @ 400-500USD)
What is a masternode?
Bitcoin:
Miner:secures the blockchain100% of block reward
Node:stores, validates and shares the blockchain
0% of block reward
Dash:
Miner:secures the blockchain45% of block reward
Masternode:stores, validates and shares the blockchain
provides higher-tier services eg mixing45% of block reward + fees1000 Dash
collateral
Denomination
mixing peer mixing peer(s)
40 dash
5 dash
23 dash
10 dash
17 dash
tx
10 dash 10 dash 10 dash 10 dash
1 dash 1 dash 1 dash 1 dash
1 dash
tx10 dash 10 dash 10 dash 10 dash
1 dash 1 dash 1 dash 1 dash
1 dash
numbers slightly simplified (no duffs)
Masternode mixing
masternode
mixing peer
mixing peer
10 dash10 dash
10 dash10 dash
10 dash10 dash10 dash10 dash
Masternode chaining
masternode
mixing peer
mixing peer
10 dash10 dash
10 dash10 dash
10 dash10 dash10 dash10 dash
mixing peer
10 dash10 dash
10 dash10 dash
10 dash10 dash
How does it look?
Dash-QT: 1
Dash-QT: Empty wallet
Request payment
Send Dash to wallet
Check Dash received
Wait for Dash to confirm
Start mixing
Mixed coins pending
Incoming denominations
Transactions
Transactions
Crea
te
Deno
min
atio
ns
Deno
min
ate
(mix
)mine not mine
Privacy threats
The nosey node attack
masternode
mixing peer
mixing peer
10 dash10 dash
10 dash10 dash
10 dash10 dash10 dash10 dash
mixing peer
10 dash10 dash
10 dash10 dash
10 dash10 dash👹
randomly chosen from a poolof (currently) 3500-4000 masternodes
chain depth2-8
Probability of snooping success
Attacker Masternodes /Total Masternodes Depth Of The Chain Probability of success
(n/t)^r DASH Required
10/1010 2 9.80e 05 10,000DASH
10/1010 4 9.60e 09 10,000DASH
10/1010 8 9.51e 11 10,000DASH
100/1100 2 8.26e 03 100,000DASH
100/1100 4 6.83e 05 100,000DASH
100/1100 8 4.66e 09 100,000DASH
1000/2000 2 25% 1,000,000DASH
1000/2000 4 6.25% 1,000,000DASH
1000/2000 8 0.39% 1,000,000DASH
2000/3000 2 44.4% 2,000,000DASH
2000/3000 4 19.75% 2,000,000DASH
2000/3000 8 3.90% 2,000,000DASH
Other threats (as of Sep 2014)
Source: Reply to Kristov's paper by Evan Duffield on Dash/forum
That’s all the threat stuff I had time to prepare
Summary
ReferencesCoinJoin Wikipedia article: https://en.wikipedia.org/wiki/CoinJoinCoinJoin: Bitcoin privacy for the real world (Greg Maxwell): https://bitcointalk.org/index.php?topic=279249Joinmarket - Coinjoin that people will actually use (Chris Belcher):https://bitcointalk.org/index.php?topic=919116.0Dash whitepaper (Evan Duffield, Daniel Diaz): https://www.dash.org/wp-content/uploads/2015/04/Dash-WhitepaperV1.pdfAn Analysis of Darkcoin’s Blockchain Privacy via Darksend+ (Kristov Atlas):http://cdn.anonymousbitcoinbook.com/darkcoin/darksend-paper/Atlas_Darksend-Analysis-v001.pdf
Top Related