-
Notifications
You must be signed in to change notification settings - Fork 119
Step by step running the tumbler
Tumbler is a JoinMarket bot which attempts to completely break the link between addresses. It is used to restore privacy where it has been damaged. It creates many many coinjoins to bounce coins around in different amounts and times.
Examples of users might be people who bought bitcoins with a very privacy-invading method, such as buying from an exchange, and wish to have privacy in all their purchases again. Some bitcoin users also just need it as a simple medium of exchange, buying bitcoins with traceable fiat and immediately spending them on goods and services. Example would be an anonymous buyer of a domain name, VPS hosting, email or VPN provisions. Users also might be those who engage in capital flight or want to store bitcoins without anyone knowing, tumbling them into cold storage. If bitcoin fungibility is ever attacked the messages "Your coins are rejected because they were used for illegal or immoral activity X transactions ago" then this bot can probably be used to solve the problem.
First create a wallet and send bitcoins to the zeroth mixing depth.
You will need two or more addresses of your destination. If you use just one address, your enemy could see X amount of bitcoins going in and then just search for an output of similar size to X. Using two or more addresses means you can split up payments into different sizes which together add up to X. Just make sure you don't then recombine them into one transaction of size X.
The tumbler.py application can be made to ask you for a new address just before it needs to send, giving you the chance to click Generate New Address on whatever service you're using and copypaste it in. (Beware: Some services like Bitstamp only allow one new address every 24 hours). If you're depositing to a normal bitcoin wallet (for example Electrum) then you can just obtain many addresses and tumbler won't need to ask you for more.
Warning: This step is very important. You CANNOT use just a single address and expect good privacy.
Run tumbler.py with your wallet file and at least one address.
It will print out an estimate of the time taken,
waits in total for 19 blocks and 35.96 minutes
estimated time taken 225.96 minutes or 3.77 hours
tumble with these tx? (y/n):
Type 'y' if you're happy to tumble. Bot will then connect to the JoinMarket pit and start doing transactions.
When tumbler.py needs another destination address, it will ask for a new address.
insert new address: 1JPFmg1RSa2gtzcsow9fBjwdvWPsxcP3eX
Come back later when the bot has finished.
Tumbler will print out a list of transactions it intends to do, carefully look through them to check. It also gives you an idea of the time taken.
tumbler transaction list
[{'srcmixdepth': 0,
'tx': [{'amount_fraction': 0.16690761108397631,
'destination': 'internal',
'makercount': 3,
'wait': 0.6},
{'amount_fraction': 0.20858522879638042,
'destination': 'internal',
'makercount': 2,
'wait': 0.24},
{'amount_fraction': 0.1228094525360878,
'destination': 'internal',
'makercount': 2,
'wait': 1.82},
{'amount_fraction': 0.37165574977649202,
'destination': 'internal',
'makercount': 2,
'wait': 0.11},
{'amount_fraction': 0.13004195780706343,
'destination': 'internal',
'makercount': 3,
'wait': 2.01}]},
{'srcmixdepth': 1,
'tx': [{'amount_fraction': 0.17961951168167614,
'destination': 'internal',
'makercount': 3,
'wait': 1.25},
{'amount_fraction': 0.34597908520497495,
'destination': 'internal',
'makercount': 4,
'wait': 2.56},
{'amount_fraction': 0.18015480070784087,
'destination': 'internal',
'makercount': 2,
'wait': 2.31},
{'amount_fraction': 0.18923022116479027,
'destination': 'internal',
'makercount': 2,
'wait': 0.28},
{'amount_fraction': 0.10501638124071778,
'destination': 'mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c',
'makercount': 3,
'wait': 1.25}]},
{'srcmixdepth': 2,
'tx': [{'amount_fraction': 0.19808511069342036,
'destination': 'internal',
'makercount': 2,
'wait': 0.03},
{'amount_fraction': 0.29131168887009173,
'destination': 'internal',
'makercount': 3,
'wait': 0.07},
{'amount_fraction': 0.037847453584973274,
'destination': 'internal',
'makercount': 3,
'wait': 0.39},
{'amount_fraction': 0.47275574685151467,
'destination': 'addrask',
'makercount': 3,
'wait': 0.45}]},
{'srcmixdepth': 3,
'tx': [{'amount_fraction': 1.0,
'destination': 'addrask',
'makercount': 3,
'wait': 1.71}]}]
waits in total for 15 blocks and 15.08 minutes
estimated time taken 165.08 minutes or 2.75 hours
An explaination of some of the labels.
- srcmixdepth The source mix depth. The mix depth in the internal wallet from where the coins will be spent from. The change address will stay in the same mix depth, the coinjoin address will be in mixdepth + 1
- amount_fraction The fraction of the coins in this mix depth to be spent in this transaction. All the fractions in a single srcmixdepth will sum to 1.0
- destination Where the coins will go. 'internal' means the coins are sent to another internal wallet address. A bitcoin address e.g. mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c means the coins are sent there. 'addrask' means the application will ask the user to input a new address.
- makercount How many market makers to use in a coinjoin.
- wait How many minutes to wait after a coinjoin transaction has been created, broadcast and mined into a block.
To get a list of parameters, run
python tumbler.py --help
It contains configuration options for various properties like makercount, waiting time, transaction count and so on.
-
The coinjoin amounts are randomly generated. If the bot generates an amount smaller than any market maker's minimum amount, your tumbler will not be able to do a coinjoin. Use this command line flag to set a floor on the coinjoin amount.
-s MINCJAMOUNT, --mincjamount=MINCJAMOUNT minimum coinjoin amount in transaction
-
If your tumbler is ended prematurely or crashes, your coins will either be still in your wallet or some might have been sent to your destination addresses. Run wallet-tool.py to see them. You may have to use the -m flag to see higher mixing depths than the default of 5. You can restart the tumbler from a higher mixing depth than zero if you just want to pick up where you left off.
-
The tumbler.py algorithm is currently based on ideas from the github issue about tumbling. https://github.com/chris-belcher/joinmarket/issues/28