Skip to content

The Bank of Web3 and Decentralized Autonomous Organizations

License

Notifications You must be signed in to change notification settings

vincenzoiovino/Bank3

Repository files navigation

The Bank3 System

Overview

The repository provides implementation of the basic version of the Bank3 protocols for Wallets and DAOs described in this note. This repo only covers a subset of the Bank3 functionalities and does focus on Ethereum.

Bank3 is essentially an anonymous deposit system (both for Wallets and DAOs) that can be described by the following example. Alice can deposit anonymously n coins in favour of Bob by sending the coins to the Bank3 contract. At any point of time Bob will hold m>n coins at the Bank3 contract, and nobody will be able to infer how much wealth Bob holds. Bob can withdraw the n coins deposited by Alice in favour of him using just the ability to use his personal wallet. After withdrawal, the fact that Alice deposited n coins in favour of Bob will be public but it will not be possible to leak how many more coins Bob holds at the Bank3.

Difference with coin mixers

Therefore, Bank3 is NOT a coin mixer but presents the following differences and advantages with respect to Trnad0 C@sh (TC):

  • A TC deposit+withdrawal can consume more than 1.3/1.4 milions of GAS whereas in our current Bank3 implementation a deposit (resp. withdrawal) costs about 68k (resp. 35k) and likely we can lower the deposit cost a bit more (e.g., with fixed notes)!
  • TC runs in fractions of a minute on powerful laptops whereas Bank3 can run in fractions of a second even on mobile devices.
  • Bank3 is user-friendly. If Alice fails to save the deposit receipt or Bob loses it, Bob can at any time do an ether scan to find all anonymous deposits in favour of him and be able to make a corresponding withdrawal.
  • Bank3 requires only hashing on-chain and as such is very portable and efficient. A slight variant of Bank3 might be likely implemented also in Bitcoin!
  • Bank3 does not require trusted setup and is based on standard computational assumptions, namely the hardness of breaking discrete logs over elliptic curves whereas it is known that any system based on SNARKs as TC cannot be proven secure from falsifiable assumptions.
  • Bank3 security is weaker than TC: after withdrawal it is visible that Bob made the deposit. This is by design: the purpose here is just to hide the Bob's left wealth at the Bank3 and not to mix the coins. This should not pose legal issues as for coin mixers.

Applications

A Bank3 for Wallets would ease the management of wallets. Indeed, in order to preserve privacy, it will not be necessary to create new accounts for each transaction. The latter mechanism is usually adopted by websites who receive donations like Wikileaks. Unfortunately, this possibility is less user-friendly for shops which might want to display a single QR code encoding their own account in order to not to deal with the creation of multiple accounts. Moreover, regulations might require declaring the amount of coins held in all personal accounts. Using the Bank3 mechanism, the withdrawable coins at the Bank3 might be considered as not part of your yearly revenues.

Another application is to the management of the treasuries of Decentralized Autonomous Organisations (DAOs) as we will show in the Bank DAO section. DAOs are not administrated by single users so the creation of multiple accounts to receive payments would be too complex and clashes with the DAO’s governance.

More applications can be achieved with the extended variants of the Bank3 protocol which are not covered in this repo and for which the reader is deferred to the original note.

This repo

The repository contains smart contract modules in Solidity and the off-chain modules written in C/Wasm-emscripten/Javascript. The focus is on Wallets but we also implemented command line tools for the DAO variant.

Live Demo

A live demo for the Wallets variant interacting with a Sepolia smart comtract is available here. Mobile browsers are not supported.

Installation for the off-chain module

./install.sh

To install the js and wasm modules, run:

make js-wasm

The compilation will use some precompiled libcrypto.a. If the compilation does not work, you may need to compile openssl with emscripten by yourself: it may require some tweaks to the Makefile, feel free to contact me if you need help.

Bank3 for Wallets: Demo

We provide a web demo for Sepolia testnet. To run the demo you don't need to install anything if you don't want the scanner functionality; see later for instructions for making the scanner functionality to work. Go to the demo folder, setup the demo with the following command:

./demo.sh

and run a web server like:

python3 -m http.server 8000

Then open localhost:8000 in your browser.

Demo: scanner functionality

This part is needed if you want the scanner functionality to work.

Install the node.js packages express, mongodb, nocache, cors, web3, e.g.:

npm install express --save

You should run a MongoDB server on localhost:27017. See here instructions to install MongoDB and run it on your local machine. We recommend you Compass to handle with MongoDB via a nice GUI.

You need an Infura API key that you can get from Infura after registration. Then fill the INFURA_KEY variable in the file server-side/bank3server.js with your key.

Finally, in the folder server-side launch the command:

node bank3server.js

Demo: instructions

  • Click on "Connect and Get Info" to connect to your Wallet and get information about yours and Bank3's accounts.
  • Click on "Add public key to ZKRegistry" to generate and add a public key into the ZKRegistry. This is a registry that eases the Bank3's account system (and not only) avoiding to request users to extract their wallets secret keys. This operation has to be done only once for all the future deposits and withdrawals and only users who want to receive deposits need to carry out this step (if you only make deposits but not wothdrawals you don't need to). You will be prompted to sign a message. Be aware that this signature will be used internally by the system as your secret password so don't sign the message in any other application or website!
  • Alternatively you can click on "Show my public key" to get your public key without actually submitting it onchain. You can then privately communicate this key to senders who wish to make a deposit for you.
  • Input the address or the public key of the person in favour of whom you want to make a deposit and the corresponding amount in ether and click on "Make deposit". After about 20secs the transaction will be accepted and you will receive an identifier associated with the deposit. Copy it or share it privately with the person in favour of whom you made the deposit. If you click on "Connect and Get Info" you should see a change in yours and Bank3's balances.
  • When you want to withdraw input a previously generated identifier and click on "Withdraw". You will be asked to sign the same message as at the time of creation of your public key into the ZKRegistry. After about 20secs your withdrawal should be successful and if you click on "Connect and Get Info" you should see a change in yours and Bank3's balances.
  • You can click on "Scan" to get a list of deposits that can be claimed by you, and by just clicking on the "identifier" field you can copy it in the "Withdraw" box.

Screenshots



Example of usage for Bank DAO

Deployment phase

We deploy both contracts solidity/bankdao/GenericDAO.sol and solidity/bankdao/BankDAO.sol. The former represents a generic DAO contract and let us suppose that its address is 9cF86D8D08bC34248210474C4B019befb0fE70fA. The constructor of the latter needs a parameter of type uint256 that can be set to 0 because it currently not used.

Initialization phase

First, we need the DAO members to compute a PK and the respective secret shares for that.

vincenzo@ubuntu:~/bank3$ ./bin/bankdao/generate_shares 3 5
s:9887DD54CD8E52F32338ECBE2B9F5220483BC55E9466BC9247950B333805BA47
PK:0x0323658C358FFD1903F2D6A405C14C23BA1420A7B13B1D8B7BF9A92024E2751E36
Share 1:39F5868C0970459F34831C83F8ABBB0BD70D569576C7FAA3F60828BD4C4B4F37
Share 2:1E3E8231BD161DA36861ABD55FD0F5CD3E30E720CD345514C133DFE859524F48
Share 3:4562D045E87FDAFFBED49AB2610F02647DA6770097ABCBE4A91830B45F1ABA7A
Share 4:AF6270C88BAD7DB437DBE91AFC65E0D1956E0634D62E5F13ADB51B215DA490CD
Share 5:5C3D63B9A69F05C0D377970F31D59115CAD8B7D6D9736E660F3840A284B99100

With the previous command we simulate a DKG protocol for 5 parties with reconstruction threshold 3 that computes a public-key PK and the 5 shares to distribute to the respective users. A full DKG protocol is not part of this implementation but either you can run the previous command on a trusted machine and modify the code so as to distribute the shares to each user over the network or you can use any secure DKG protocol among the parties for the secp256k1 curve. In the latter case you can still use the next commands without any change. Henceforth, we assume that user i=1,...,5 has the share i shown above. The user can be a DAO member or even an external party (e.g., accountant, administrator).

Now, we can invoke the function setPK of the contract GenericDAO.sol with input parameter the public key PK shown before.

Deposit phase

Now suppose a user Alice wants to deposit 1000 wei in favour of the generic DAO contract. Then, it executes the following command:

vincenzo@ubuntu:~/bank3$ ./bin/commons/encrypt 0323658C358FFD1903F2D6A405C14C23BA1420A7B13B1D8B7BF9A92024E2751E36 9cF86D8D08bC34248210474C4B019befb0fE70fA
A:0x025E7C20C190C943A02C1C1456ADCD60BB60F7F67618A96B55D9FFD492A483CE87
B=0x65004d5d2d63ace0a6e855060be78f09e24ad0fd6a56cced9723cf093fea8ba7

The first argument to the program is the previously computed public key PK and the second is the address of the generic DAO contract. Also, note that our programs take as input hexadecimal strings without the prefix 0x whereas for the transactions you will need to submit on-chains the prefix is needed.

Alice can invoke the method MakdeDeposit of the BankDAO.sol contract with inputs the values A and B from the above output and setting as value for the transaction 1000 wei. If the transaction was successfull, it will return an identifier id that for the first execution will be just the integer 0. You can observe that the Bank DAO contract's funds increased by the corresponding quantity. Alice can pass the identifier id privately to the DAO members as reference for future withdrawals. This is not really needed but makes the withdrawal more efficient.

Approval phase

Suppose that the DAO members of the generic DAO contract or some of them are aware that they hold at the Bank 1000 wei and they want to withdraw from the Bank 100 wei. They can make a proposal to withdraw such amount of coins. We suppose that proposals are associated with an index t of type uint256 and there is an hash map proposals from uint256 to uin256 such that proposal[t]=x iff the proposal t concerned the withdrawal of x coins and has been approved. So, a DAO needs just to update the map proposals in order to be compatible with the Bank DAO. So let us suppose that this is done, that is proposals[1]=100. This is done in the contract GenericDAO.sol using the method ApproveProposal(uint t,uint256 nCoins).

Withdrawal phase

Off-chain part

Since the generic DAO was sharing the public key via a protocol with threshold 3, we need 3 members to participate in the witness computation phase that occurs off-chain. Let us suppose that the users to participate in the reconstructions are the users 1,2,4. Then, user 1 on his computer runs the following command:

vincenzo@ubuntu:~/bank3$ ./bin/bankdao/compute_share_for_withdrawal 025E7C20C190C943A02C1C1456ADCD60BB60F7F67618A96B55D9FFD492A483CE87 39F5868C0970459F34831C83F8ABBB0BD70D569576C7FAA3F60828BD4C4B4F37
Share to broadcast to other users (along with your user index): 03EC43DF01687023902B177F3BC33A3DB389AD68341A602C97A7F4A0B635647888

The first argument to the above program is the value A computed before by the program encrypt and the second is the share of user 1 (cf. the execution of the program generate_shares). Similarly, user 2 (but with his own share that is different from the one of user 1):

vincenzo@ubuntu:~/bank3$ ./bin/bankdao/compute_share_for_withdrawal 025E7C20C190C943A02C1C1456ADCD60BB60F7F67618A96B55D9FFD492A483CE87 1E3E8231BD161DA36861ABD55FD0F5CD3E30E720CD345514C133DFE859524F48
Share to broadcast to other users (along with your user index): 032517096E7A35CE9E43B152E203B2163933A747F9BEEE75E904BE386BB7F4391D

And user 4:

vincenzo@ubuntu:~/bank3$ ./bin/bankdao/compute_share_for_withdrawal 025E7C20C190C943A02C1C1456ADCD60BB60F7F67618A96B55D9FFD492A483CE87 AF6270C88BAD7DB437DBE91AFC65E0D1956E0634D62E5F13ADB51B215DA490CD
Share to broadcast to other users (along with your user index): 029765BB499A59D5EEB97A4FBDEE9F872C13ABD2547B9AD3036101C74B58D81E13

Let us call S1,S2,S4 be the outputs of the previous program executions respectively for users 1,2,4. Now, the users 1,2,4 can broadcast each other their values S1,S2,S4. They can do that e.g. via e-mail. Now, any of them can execute the following program to compute the witness C that is actually needed to make a withdrawal:

vincenzo@ubuntu:~/bank3$ ./bin/bankdao/witness_for_withdrawal 3 1 03EC43DF01687023902B177F3BC33A3DB389AD68341A602C97A7F4A0B635647888 2 032517096E7A35CE9E43B152E203B2163933A747F9BEEE75E904BE386BB7F4391D 4 029765BB499A59D5EEB97A4FBDEE9F872C13ABD2547B9AD3036101C74B58D81E13
Witness C: 023C9C232F8D527AB5780BC679185424DBCA273DFAA4E1D48B501AF2D28B8AE25E

The program takes as input the threshold 3 and the values 1 S1 2 S2 4 S4 where S1,S2,S4 are as specified before. The value C in the output of the previous execution is the witness that will be used to make the withdrawal.

On-chain part

Let us say that the user 1 is responsible to make the withdrawal. The user 1 invokes the method MakeWithdrawalSha256 of the Bank DAO contract with the following parameters:

  • t=1, the proposal accepted in the Generic DAO.
  • nCoins=100, the amount of coins to withdraw from the Bank.
  • addr=9cF86D8D08bC34248210474C4B019befb0fE70fA , the address of the generic DAO contract in favour of which the withdrawal is performed,
  • id=0, the identifier of the deposit of Alice that was for the amount 1000wei >100 wei).
  • C=0x023C9C232F8D527AB5780BC679185424DBCA273DFAA4E1D48B501AF2D28B8AE25E, the witness computed above. The transaction will transfer 100 wei from the Bank contract to the generic DAO contract. With the same witness you can actually repeat the same process 10 times until all 1000 wei consume the deposit of Alice.

The user can also do the previous procedure by replacing MakeWithdrawalSha256 with MakeWithdrawalKeccac256 but in this case in the deposit phase it should use the program encrypt_keccac instead of encrypt.

Note: the example shows the withdrawal of 1000wei from a transaction of 100wei. This is not meaningful because after the withdrawal it might be possible for an attacker to withdraw the rest of 900wei in the transaction. However, our system is general and allows this sort of partial withdrawals. For instance, unclaimed coins could go for donations, etc.

References

Vincenzo Iovino. Bank3: enabling deposits and withdrawals from Wallets and DAOs in a private and decentralized way, 2023.

About

The Bank of Web3 and Decentralized Autonomous Organizations

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages