Later this month I will be launching a unique service aimed at making your Bitcoin history private in a provable way, something that was suggested for a long time, but has not been done until now. The goal of this topic is to start a discussion about this model and get as much feedback as possible from the community prior to launch.
Brief DescriptionThere will be 1 aggregate address for all deposits and withdrawals
There will be
2 modes,
fast and
slowThe
fast mode works like most other tools where you get a deposit address, you select the number of withdrawal addresses together with the amount for each and the time delay (0-200 hours), and then you receive the Bitcoins to the indicated addresses.
The
slow mode allows you to deposit Bitcoin and instead of sending all your Bitcoins to new addresses now, you get a “Note” in return. With this Note you can come back later at any point in time and withdraw any amount from it to as many addresses as you want. The notes can also be combined together so that you can have full control over the process. As an example you could deposit 0.5 BTC 5 times and get 5 different notes, combine them together and withdraw 1.5 BTC after 2 weeks and the remaining 1 BTC after another 2 weeks, making it very hard for any outside observer to know where your BTC came from since the originating transactions could have happened at any point since the launch of the service and both of your outputs are higher than any of the inputs.
These 2 modes both have one big drawback, your transactions are anonymous to the public but are not anonymous to us since there is no way for us to reliably prove that we enforce the strict no-logs policy. We came up with a solution to this issue, the
Blind Certificates, which you will find out more about later on.
Detailed DescriptionSince we are using a single aggregate address for all deposits and withdrawals, holding its private key on a server would be a risky move. That is why we decided to use a backend+validator model. The backend’s job will be to interact with end users by generating deposit addresses, processing withdrawals, minting/burning blind certificates (explained below), etc. In the initial design, there will be x validators which will validate all of the backend’s actions (verify funds were received from the deposit address to the main aggregate address, verify submitted blind certificates or credit notes for withdrawals). These x validators will hold the multi-sig keys for the main address and will be hosted on different servers. Whenever a withdraw transaction is being sent, the signatures must be retrieved from all validators which are able to verify the transaction is correct. If an attacker manages to gain access to the backend, it would be pointless, as he will not be able to steal the funds (since the keys are on different servers), and he will not be able to forge proofs in order to withdraw another user’s BTC to his wallet. Using this model, we will be able to further decentralise this service by allowing other trusted members to run their own federated validators so that a single entity will no longer hold all of the multi-sig keys.
When a user deposits BTC using the fast withdraw method, the backend sends the deposit hash to the validators and whitelists the receiving addresses. After the signature is sent to the backend, the validators delete all proofs of those receiving addresses, keeping only the deposit transaction hash so that they would not accept a “duplicate proof”.
When a user deposits BTC using the slow withdraw method, the backend sends the deposit hash to the validators and they assign credit to the note’s public key. When the user wants to withdraw his BTC, he must send a signature to the backend which will process this. This signature will also be sent to the validators which will check it and remove credit from the note’s public key and whitelist the receiving addresses. If an attacker compromises the backend server, he would not be able to forge user note signatures in order to fool a validator to send him funds, because only the users have access to the notes’s private keys. Again, the proofs are deleted after their use.
But what if you don’t trust us? What if you don’t believe that we will delete these validator proofs? Well, this is where the Blind Certificates come in handy. You will be able to redeem your note received from a slow deposit in order to mint blind certificates. There will be 0.01, 0.1, 1 and 10 BTC blind certificates. For example, if you have a 11.245 BTC credit in your deposit address, you will receive a 10 BTC certificate, a 1 BTC certificate, 2 0.1 BTC certificates and 4 0.01 BTC certificates. You will be able to download all these certificates at once (probably in a ZIP file generated by the frontend), and then spend them however you like. The rest of 0.005 BTC will be left in the main wallet. You will then be able to redeem these certificates for credits in new notes, which you will then be able to use for withdrawals.
Blind certificates work in such a way that, even if we logged every single action, we would still not be able to connect a deposit -> note -> blind certificate action to its corresponding blind certificate -> note -> withdraw action.
We decided to use Groth16 ZK-SNARKS for this, instead of blind signatures, because of an important security problem in our architecture with blind signatures: if the private key which is used for the blind signatures is stored on the backend server, an attacker which compromises it would be able to forge certificates which the validators will trust, and therefore draining the wallet, basically making the backend+validator architecture useless. With a ZK-proof, the attacker would not be able to do this, because the secret witnesses used to prove a certain withdraw is valid is generated by the user in the frontend, so not even the backend can forge these proofs. At some point, we will make the frontend open source, which will reveal all of the backend’s endpoints, so you can build/host your own frontend for this, or even create a CLI. The architecture is really similar to Tornado Cash’s architecture: we store a merkle tree of the users’s public statements in the database. When a user redeems a note for certificates, we store the user’s public statements in the tree. When a user wants to redeem the certificates for a note, the frontend, using the user’s secret witness, will be able to prove to the backend (AND the validators) that he has the secret witness of a certain leaf in the tree, without actually saying which leaf it is. This makes it totally anonymous towards us, the operators, as well.
We decided to use Tornado Cash’s exact ZK-SNARK circuit for 2 reasons:
A) Groth16 circuits require a setup procedure in order to generate verifying and proving keys (both public) to make the whole ZK system work. This must be done in a multi-party process called a ceremony. When generating these keys, multiple parties must participate. The more the better, since the circuit only becomes compromised if 100% of the participants acted with malicious intent. The ceremony which generated Tornado Cash’s circuits keys was one of the biggest ceremonies of this kind (1114 participants), so it’s highly unlikely that the circuit could be compromised. You can read more about it here:
https://tornado-cash.medium.com/the-biggest-trusted-setup-ceremony-in-the-world-3c6ab9c8fffaB) The system is battle tested. All of the system actions with Tornado Cash are completely public to everyone (in our case, theses actions would only be public to us), and it’s still 100% anonymous.
Looking forward to your questions/suggestions!
References: (
https://www.reddit.com/r/Bitcoin/comments/5ksu3o/blinded_bearer_certificates/)
https://theymos.com/case_for_bcerts_18.pdf