owned this note
owned this note
Published
Linked with GitHub
# Bank3: enabling deposits and withdrawals from Wallets, DAOs and real-world identities in a private and decentralized way
## Setting and motivation
In this note we put forth a proposal for what we term *Bank3*.
Bank3 is essentially an anonymous deposit system both for Wallets and DAOs and supporting identity-based features. The identity-based part is based on the [League of Identity system](https://hackmd.io/noiVZo2dTJ6Wiejt2IJvMg?both) (LoI) and only outlined here and we defer the reader to the LoI's documentation for details.
A *Bank3 for Wallets* (or just Bank3) is a smart contract $B$ which Ethereum users can deposit coins (ETH) to and withdraw coins from.
A *sender* is a party who wants to deposit coins to a given user Bob via the Bank3. When making a deposit, a sender specifies the amount of coins $n$ to be transferred and a *receiver* address, that is the address of an Ethereum user who can later claim the coins.
Bank3 can be described by the following example. A sender Alice can deposit anonymously $n$ coins in favour of a receiver Bob by sending the $n$ coins to the Bank3 contract. At any point of time Bob will hold $m\ge n$ coins at the Bank3 contract and can check that, but nobody else will be able to infer how much wealth Bob holds at the Bank3.
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 the $n$ coins in favour of Bob is public but it is not possible to leak how many more coins Bob holds at the Bank3.
### Security properties
Precisely, the Bank3 protocol preserves privacy in the following sense. After a withdrawal an attacker should not be able to infer the left quantity of coins that the Bank owes to Bob (that is, the amount of coins that Bob can still withdraw from the Bank).
This corresponds to the real-world scenario in which Bob withdraws $10k$ euros at the desk of a bank and other customers in the room can see that. So people can infer that Bob owns at least $10k$ euros but they should not be able to know if Bob owns other $300k$ euros or Bob has just $10$ euros left at the bank.
While in the traditional bank scenario the bank's employees can display the Bob's balance, Bank3 is completely decentralized and there is no party at all (except Bob himself) who can infer how much coins Bob holds at the Bank3 at any given point of time.
An implication of this property is that each deposit is anonymous until the corresponding coins are withdrawn, that is a deposit does not leak the address of the receiver.
Observe however that it is unavoidable that an adversary can corrupt senders and infer that Bob owns at least the quantity of coins deposited by corrupted senders, that is if Alice and Charlie deposit resp. $2$ and $3$ coins in favour of Bob, an attacker who corrupts Alice and Bob can infer that Bob holds at least $5$ coins at the Bank3.
Another natural requirement of the Bank3 protocol is that only the receiver Bob of a deposit should be able to claim coins from a deposit and nobody else should be able to perform their withdrawal.
We will also consider a [*light dark*](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?view#Dark-variant) variant of Bank3 in which we can have the receiver to be able to withdraw a deposit in favour of *any* address while hiding the actual receiver of the deposit.
That is, Alice can be able to make a deposit in favour of Bob by specifying just some Bob's public information which will be hidden in the deposit even at withdrawal time. Bob can withdraw the deposit from any other pseudonymous Eth address without disclosing that the original deposit was in favour of Bob.
The drawback in this case is that Alice can act as receiver as well, that is she can withdraw the coins on behalf of Bob.
### Applications
#### Management of wallets
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.
#### Anonymous deposits in favour of any address of any blockchain
In the [light dark](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?view#Dark-variant) variant of Bank3 we can have the receiver to be able to withdraw a deposit in favour of any address, and thus a shop could still display a single address to receive payments but with the possibility of withdrawing a given deposit from any other address without leaking that the deposit was in favour of the shop.
Another application is to enable deposits in favour of users of other blockchains.
Alice can pay Bob in ETH even if Bob owns only a Bitcoin address at time of deposit. At any time Bob can use his Bitcoin Wallet to make the withdraw in ETH; for this he needs to create an ETH account but this can be done only at withdrawal time. In our system, the Bitcoin's public key will be hidden even after withdrawal.
#### Generalization to the identity-based setting
The main feature we envision is that the payment can be done in favour of email addresses or phone numbers, any other OAuth provider (Facebook, Twitter, ...) and social security numbers associated with digital identity cards as we propose for our [identity-based variant](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Identity-based-and-BLIK3-variant).
#### Management of DAOs
Another application is to the management of the treasuries of Decentralized Autonomous Organisations (DAOs) as we will show later. 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.
#### Incentive mechanisms
Bank3 can work as a real *bank* by staking the coins of the users, making profit from it and distributing the revenues to the users.
#### Fallback mechanisms
A natural functionality that can be added to Bank3 is a fallback mechanism in which a deposit that is unclaimed for long time can be claimed by the sender and
in the case in which the sender does not claim it for long time the unclaimed coins can be spent by the Bank3's organization.
Also, the deposits made into the smart contract can be set so that the sender has some time (e.g. 48h) to claim it back in case of a mis-payment.
#### Proofs of liquidity
Our protocol enables efficient proofs of liquidity, that is one can prove to own a given amount of coins, and the proof can be both transferable or non-transferable, and tied to a real world identity (your email address) or not.
#### Compressed deposits
Another application is to compress deposits so as to save transaction costs. That is, an employer can perform a single deposit to all of its e.g. 100 employees so as to enable each employee to withdraw at any time. This application makes sense independently from the additional anonymous features our system supports and is presented [here](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Succint-group-deposits).
## Differences with coin mixers
Unlike a coin mixer like Tornado Cash (TC), in a Bank3 system a withdrawal shows where the coins come from (the address of the sender can be deduced).
We can sum up the differences between Bank3 for Wallets and TC as follows.
* 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!
* TC runs in several seconds 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. Moreover, Alice does not necessarily need to communicate with Bob before the payment (we propose though variants in which this is necessary but we never require Bob to store additional secrets). Instead, in TC Alice and Bob always need to coordinate before the payment and in addition Bob needs to store a secret.
* Deposits in faovur of public keys of identities of other system. Bank3 allows Alice to deposit e.g. $1$ ETH in favour of Bob without Bob having an Ethereum wallet yet. Alice can specify a Bob's Bitcoin public key for the deposit or the email address of Bob.
* Bank3 requires only light cryptography on-chain (with the basic variant requiring just hashing) 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, and requires much simpler cryptography than TC.
* Bank3 security is weaker than TC: after withdrawal it is visible that Alice 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. However, if Alice specified in the deposit a Bob's Bitcoin or email address, this *intended identity* will be hidden even at withdrawal time. We additionally propose variants that attains a plausible level of $1$ out of $m$ privacy, both on-chain and for off-chain proofs of liquidity.
Our inter-chains and identity-based payments can be implemented at low cost in Bank3 whereas in TC these features would require a substantial changes in the design that significantly would impact the efficiency.
### Related work of Dunaif and Boneh
In a [hackmd note](https://hackmd.io/nCASdhqVQNWwMhpTmKpnKQ) Dunaif and Boneh introduce a private DAO system whose wished goals (and non-goals) are exactly identical to our [Bank DAO](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Our-Bank3-protocol-for-DAOs) system.
We came across this note only in February 2024 and we informed Dan Boneh.
Though the security properties and functionalities are similar, our system diverges from theirs in several aspects.
Our system enables deposits in favour of intented receivers of public keys or identities of other systems (e.g. a Bitcoin public key or an email address) and this receiver identity is hidden even at withdrawal time. That is, if Alice deposits $1$ ETH in favour of Bob using Bob's Bitcoin public key $A$ and Bob's ethereum address $B$, when Bob withdraws $B$ is revealed but $A$ is still hidden.
In ours the DAO managers who want to withdraw the coins corresponding to a deposit perform only hashing on-chain whereas in the Boneh and Dunaif's design the smart contracts must perform the verification of Schnorr' proofs of knowledge which consumes much more gas than the single hash in ours. Moreover, Dunaif and Boneh do only focus on DAOs and do not take in account wallets and our [extensions](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Extensions).
### Relation with stealth addresses
A similar proposal as ours is the one of [stealth addresses](https://vitalik.eth.limo/general/2023/01/20/stealth.html) of which we became aware only after we designed ours.
The main differences are the following.
Unlike stealth addresses, deposits in our system are tied to the Bank3 smart contract and this offers the following advantages.
The overall amount of assets of the bank can be staked and the revenue can be shared among the users. This may give incentives to users to receive payments through the Bank3 system.
One notable issue with crypto payments is mis-payments to wrong addresses (error correction techniques only partially solve the issue because a sender can always select a wrong receiver from a list).
Moreover, many crypto assets in the real world get lost. In Bank3, deposits unclaimed for long time (e.g. a couple of years) can optionally come back to the sender with a small fee to the Bank.
The Bank3 contract can be designed so that a sender has some some time (e.g. 48h) to claim back the deposit.
The Bank3 system naturally enable to avoid transaction fees for receivers in the following way.
Moreover, Bank3 covers the DAO setting and to the identity-based setting that is not directly covered by stealth addresses.
Equivalently we can say that Bank3 is a generalization of stealth addresses to DAOs and identity-based settings with fallback, staking and other features only allowed by a specialized smart contract as Bank3.
## Our basic Bank3 protocol for Wallets
Suppose a sender Alice wants to send $n$ coins to a receiver Bob identified by the address $addr$ on the Ethereum blockchain. We suppose for now that Alice knows a public key $PK_B$ of Bob, we will later discuss how this can be implemented in a user-friendly way.
In the Bank3 protocol, the sender computes (off-chain) the following values:
$A=g^r,C=PK_B^r$, where $PK_B$ is the Bob's public key of the form $g^{sk_B}$ and $r$ is a random value $\in Z_p$, and sets:
$CT=(A, B=H(C) \oplus H(addr))$, where $H$ is SHA256 or Keccac.
The value $C$ is called th *witness*.
Then, the sender submits to the Bank3 smart contract the tuple $(n,CT=(A,B))$ along with a deposit of $n$ coins.
The Bank3 stores $(n,B)$ in a hash table and the transaction fails if $B$ was already in the hash table so as to prevent replay attacks. Note that it is not necessary to store $A$ in the Bank3 smart contract, we just need this value retrievable via an Ether scan so as to be used for off-chain computations (see later).
Suppose now that the Bob wants to withdraw the $n$ coins corresponding to the deposit for the value $CT=(A,B)$ from the Bank3.
To withdraw the $n$ coins from the Bank DAO, Bob can send to the Bank3's contract $(addr,C)$, where $C=A^{SK_B}$.
Then, the contract of the Bank3 does the following checks:
* 1. $H(C) \oplus H(addr)=B.$
* 2. In the hash table corresponding to B, it holds that n>0.
If all checks pass, the Bank3 contract updates $(n, B)$ with $(n=0,B)$ to indicate that $n$ coins have been withdrawn, and finally the Bank3 transfers $n$ coins to Bob.
We remark that $B$ could be alternatively computed as $H(C,addr)$.
#### Remark on malleability
The previous protocol can be subject to the following front-running attack that can affect the privacy as pointed by Daira Hopwood.
An attacker (e.g., a miner) could observe a transaction corresponding to a deposit of $n$ coins with value $B$ and could decide to replay this value in another transaction with higher amount $m>n$ of coins. In this way, Bob could be tempted to withdraw earlier so as forcing Bob to reveal his identity. This can be fixed by including the amount of coins $n$ in the witness to be hashed so as to bind the value $B$ to the value $n$, precisely we can replace $H(C)$ with $H(C,n)$. Henceforth, in the rest of this note, whenever possible we will assume that this is the case omitting this detail.
We remark that this issue is also present in TC if the value deposited on-chain is not bound to the amount of coins to be deposited.
#### Usability issues and implementative details
We must specify how Bob generates and distributes his public key $PK_B$. One possibility is to make Bob use his own Ethereum public key (the one corresponding to his Ethereum address).
The issue is that Bob would then need to extract his secret key from the wallet and this is not really ideal.
To address these issues we propose to adopt the [ZK Registry](https://github.com/aragonzkresearch/nouns-anonymous-voting/blob/main/contracts/src/ZKRegistry.sol) (ZKReg) proposed by Aragon ZK Research for different but similar purposes.
The ZKReg is just a map between Ethereum's addresses and public keys. Alice can associate her own Ethereum address to a public key whose secret key is generated by a password chosen by hers.
For instance this password can be deterministically generated as signature of a known message like "Don't sign this message for any application different than the ZKReg"; in this way Alice does not need to know any additional secret beyond her wallet's password.
In the current design we stick to the ZKReg solution adding the following feature: the user can choose to compute the "ZKReg" public key without actually submitting it onchain. In this way, the user can privately communicate such public key to senders in order to receive deposits.
Another practical option could be to use encryption (e.g. ECIES) to encrypt the witness $C$. Indeed, our system can be seen abstractly as encrpyting some witness $C$ and publishing the resulting cipherthext and the hash of $C$ (and other info) on-chain. Ethereum Wallets should enable ECIES decryption so this solution should be practical modulo technical details that depend on the Wallet APIs.
## Our Bank3 protocol for DAOs
A *Bank DAO* (or *Bank3 for DAOs*) is a smart contract $B$ which other DAOs can deposit coins (ETH) to and withdraw coins from.
The word *DAO* in "Bank DAO" is meant to recall the idea of a bank service for other DAOs but the Bank DAO is just a smart contract without governance functionalities, so a preferable name might be *Bank of DAOs*.
We assume that each DAO $D$ has a public key $PK_D$ registered in its own contract and there is a public method in each DAO $D$ that wants to make use of the Bank DAO service to enable anyone to retrieve the public key of $D$.
The secret key $sk_D$ corresponding to $PK_D$ has the form $g^{sk_D}$ for some generator $g$ of a cyclic group of prime order $p$, where the secret key $sk_D$ is shared among $D$'s members in a threshold way. The secret sharing is done off-chain, that is there are no traces on-chain of the shares of $sk_D$ or of whoever belongs to the set of participants who share $sk_D$.
We can assume the public keys to be Ethereum-like (curve secp256k1) but our approach is generic and we could generalize to different curves or class of public keys.
The participants who share $sk_D$ may be even outside the DAO $D$ (e.g., administrators, accountants, etc.), and $PK_D$ can be re-shared periodically so as to guarantee that the public key is the same but the set of participants who share $sk_D$ changes over the time. However, for simplicity we will assume that a withdrawal of coins in favour of a DAO $D$ is done by members of $D$.
In our model we do not deem a security breach the case in which a sender Alice who made a deposit of $n$ coins in favour of a DAO $D$ is later able to withdraw up to $n$ coins in favour of $D$ without permission of $D$ (it would be an attack only if Alice were able to withdraw $\le n$ coins in favour of herself or in favour of any other DAO $D'$ different from $D$).
Suppose a sender wants to send $n$ coins to a DAO $D$ identified by the address $addr$ on the Ethereum blockchain.
In the Bank DAO protocol, the sender computes (off-chain) the following values:
$A=g^r,C=PK_D^r$, where $PK_D$ is the $D$'s public key of the form $g^{sk_D}$ and $r$ is a random value $\in Z_p$, and sets:
$CT=(A, B=H(C) \oplus H(addr))$, where $r$ is a random value $\in Z_p$ and $H$ is SHA256 or Keccac.
Then, the sender submits to the Bank DAO's smart contract the tuple $(n,CT=(A,B))$ along with a deposit of $n$ coins to the Bank DAO.
The Bank DAO stores $(n,B)$ in a hash table. Note that $A$ is not stored by the smart contract of the Bank but it will be visible on the blockchain so as to be used for off-chain computations (see later).
Suppose now that the DAO $D$ wants to withdraw $n$ coins from the Bank DAO.
We propose that the DAO $D$ makes a proposal to withdraw $n$ coins from the Bank DAO. The proposal is made in a standardized way so that the Bank DAO can query $D$'s contract to check if a proposal to withdraw such amount of coins was actually submitted and *accepted*. We skip the details of how this is done but we remark that this can be done in an efficient way.
Suppose that a proposal to withdraw $n$ coins from the Bank DAO has been voted and accepted on the DAO $D$ and suppose Alice is a member of the DAO $D$. Suppose $t$ to be the number of such proposal on the DAO $D$.
To withdraw $n$ coins from the Bank DAO, Alice can send to the Bank DAO's contract $(t,n,addr, C)$.
We will show later how Alice can compute $C$ in a threshold way.
Then, the contract of the Bank DAO gets $PK_D$ by querying the contract $addr$ and does the following checks:
* 1. $H(C) \oplus H(addr)=B.$
* 2. In the contract with address $addr$ of the DAO $D$ the proposal number $t$ agrees to withdraw $n$ coins from the Bank. This can be done by a simple query to the DAO $D$, that is there should be a public method implemented in all the contracts that want to make use of the Bank DAO protocol that on input an integer $n$ outputs $1$ (resp. $0$) to denote that the last proposal concerned the withdrawal of $n$ coins and it was accepted (resp. rejected).
If all checks pass, the bank contract updates $(n, B)$ with $(0,B)$ to indicate that $n$ coins have been withdrawn, and finally the Bank DAO transfers $n$ coins to $D$.
(Additional checks have to be done to guarantee that $D$ cannot withdraw more coins that $D$ holds in the Bank but for simplicity we skipped those tedious details.)
The Bank DAO should also implement a mechanism to keep trace that the proposal number $t$ of the DAO $D$ cannot be longer used to withdraw coins.
This can be done by setting a lock flag in the $D$'s contract whenever the Bank DAO queries $D$ to know if the proposal $t$ is in favour of withdrawing $n$ coins so that $D$ will answer negatively to any such future query if the flag is set.
### The efficient threshold computation of $C$
Recall that our ciphertext has the form $(A=g^r,B=H(PK_D^r)\oplus H(addr) =H(g^{SK_D\cdot r}) \oplus H(addr))$, where $r\in Z_p$ and $sk_D$ is the secret key corresponding to $PK_D$ and $H$ is SHA256 or Keccac.
Let us suppose that the $D$'s members shared $sk_D$ by means of a $t$ out of $N$ secret sharing.
Let $S$ be a subset of $[N]$ of cardinality $t$ and for each $i\in S$ let $\lambda_{S,i}$ be the corresponding Lagrange coefficient.
For simplicity let us suppose that $S=\{1,...,t\}$, and that $sk_1,\ldots,sk_t$ are the shares of $sk_D$ of the members in the set $S$.
Then, the $t$ members of $S$ can compute (off-chain) the following values:
$A_1=A^{\lambda_{S,1}\cdot sk_1}, A_2=A_1\cdot A^{\lambda_{S,2}\cdot sk_2}, ...,A_t= A_{t-1}\cdot A^{\lambda_{S,t}\cdot sk_t}$.
This can be done by having each member of the set sending a single value to each other (e.g. via email). In particular, the generic member $i$ needs to broadcast to the other members the value $T_i=A^{sk_i}.$ The values $T_i$'s can be used by each member to compute the value $A_t$ that, by the properties of the Lagrange coefficients, is equal to $PK_D^r=C$, as we had to show.
So, we can suppose that the previous threshold protocol ends up with Alice (as any other member of the set) knowing the value $C$ needed to trigger the withdrawal.
## Beyond the basic system and extensions
### Light dark variant for Wallets, intented receiver anonymity and handshake variants
We can consider the following variant that we term *light dark*.
The receiver sets the value $addr$ to a fixed canonical address (e.g., the address of the Bank3 smart contract).
In this way, it will not visible at any point which receiver's identity the sender specified at *deposit time*. This is useful to perform payments to Bob on Ethereum before Bob have already created an Ethereum account having only some Bob's public key representing e.g. a Bitcoin public key or, as we will see later, an email address or phone number.
This also covers the case in which the public key is for a threshold Schnorr/EC-DSA/BLSG scheme that is shared by different users who can decide at any time to jointly perform the withdrawal in favour of any specific ETH address.
Here, we say that e.g. the Bitcoin's public key or email address specified is the *intended receiver* of the deposit whereas the actual Ethereum address $addr$ in favour of which the withdrawal will be performed is the actual receiver.
A nice property or our system is that at withdrawal time the actual receiver $addr$ will be revealed but the intended receiver will be still hidden, that is we achieve *intended receiver anonymity*.
The drawback of this variant is that the sender, after having done a payment, can withdraw it at any time acting as receiver. That is, the sender can change his/her mind at any point and take back the coins and the alleged receiver will be always doubtful about being able to claim a deposit.
Moreover this variant is subject to front-running attacks by a miner who can censor the honest withdrawal transaction and use the witness to perform the withdrawal in its favour by sending a transaction from its account.
This can be sidestepped by using a commit and reveal approach in two transactions or using timelock encryption to temporarily hide the witness.
The solution we propose is the following.
Bob chooses random value $s\in Z_p$ and computes $g^s,A'=A^s, C'=C^s$. Bob computes a non-interactive Chaum-Pedersen (CP)'s proof of knowledge $\pi_1$ of the fact that $(A,C,A',C')$ is a valid Diffie-Hellman (DH) tuple. Bob also computes a non-interactive CP's proof of knowledge $\pi_2$ of the fact that the tuple $(g,g^s, PK'=PK^s, C')$ is DH. Both proofs along with $C$ are sent and on-chain and if the verification is successful this convinces the verifier that Bob knows $sk=dlog_A C$.
In addition Bob can sign the address $addr$ to which he wants to receive the coins using a Schnorr's signature with respect to the pair $(g^s, PK'=g^{s\cdot sk})$. The overall cost is dominated by $10$ point multiplications.
Another option that requires to perform less cryptographic operations on-chain is to additionally include a public key $PK$ as part of the pre-image and at withdrawal time Bob is required to provide a Schnorr's signature with respect to $PK$ of the address to which Bob wants to receive the coins. The secret key $sk$ corresponding to $PK$ can be computed in a deterministic but unpredictable way as signature under the Bob (the receiver)'s public key $PK_{Bob}$ used by the sender to make the deposit (e.g. the Bitcoin's public key of Bob) of a message that depends on withdrawal witness $C$. In this way, Bob uses his Bitcoin's public key to compute the witness $C$, signs $C$ under the same public key to derive a secret $sk$ from which he can compute $PK$ and the Schnorr's signature of the Ethereum address $addr$ to which Bob wants to transfer the coins.
Observe that this variant needs the public key $PK$ to be communicated to the sender before payment. When there is a communication before or during deposit we talk about an *handshake* variant. All our handshake variants are user friendly in that they do not require the receiver to save any secret.
An alternative is for $PK$ to be equal to the the Bitcoin public key $PK_{Bob}$ but this discloses the identity of Bob at withdrawal time. If intended receiver anonymity is not needed, indeed, another solution is for the sender to deposit the coins along with the values $A=g^r, B=PK^r$, where $PK$ is e.g. a Bob's Bitcoin public key and request Bob to withdraw in favour of an ETH address $addr$ by sending on-chain a signature of $addr$ under public key $PK$, thus also revealing $PK$.
Another handshake variant that offers several efficiency benefits is the following.
Alice, who wants to send $n$ coins to Bob via Bank3, does the following. Alice sends a random challenge $e$ to Bob which uses his Metamask secret key to sign $e$ hence producing a signature $sig$. Bob computes $C=Hash(sig)$ and sends back $Hash(C)$ to Alice who sends to the Bank3 smart contract $(n,e,Hash(C) \oplus Hash(addr)),$ where $addr$ is the Bob's address along with a transfer of $n$ coins.
At any time Bob can see $e$ and recomputes the signature $sig$ and so $C$ and sends $Hash(C),addr$ to the Bank3 contract as witness for the withdrawal.
#### Paying fees
A problem shared with stealth addresses is: who is going to pay transaction fees to withdraw funds in favour of an address with possibly zero coins?
In the case of the Bank3 system we can address this issue as follows.
In the above light dark variant, in order to withdraw, the receiver needs to send a transaction that includes a signature (under a public key that is hidden in the deposit) of the address to which the receiver wishes to receive the funds. The receiver can forward this signature to a server of the Bank3 system that is just responsible of submitting this transaction on-chain and paying the corresponding fees. This can be a freemium or paid service offered by the Bank3 system.
### Post-quantum security
Abstractly our basic Bank3 system can be seen as having Alice to choose a random value $C$, encrypt $C$ under the Bob's public key to produce a ciphertext $CT$ and submit on-chain $(CT,Hash(C))$ along with a transfer of a certain amount of coins.
It is easy to see that this can be made post-quantum secure by using a post-quantum secure KEM.
### Identity-based and BLIK3 variant
See [here](https://hackmd.io/noiVZo2dTJ6Wiejt2IJvMg?view#Polish-BLIK-for-web3) for the identity-based variant of our system.
### Proofs of liquidity and $1$ out of $m$ privacy
We can add additional functionalities and upgrade the system to a ZeroCoin-like system with a higher level of privacy as we will describe next.
First, we observe that abstractly the system can be seen as follows.
The sender publishes on-chain a ciphertext $CT$ encrypting a random value $x$ under the receiver's public key $PK$ along with a value $y=f(x)$ for a one-way function $f$. We assume the encryption scheme to be anonymous, that is the ciphertext hides the public key, a property satisfied by all practical schemes. In the standard Bank3 system the encryption scheme is implicit in the usage of the Diffie-Hellman tuples and $f$ corresponds to an hash function.
Observe that for sake of simplicity we omit to specify the address of the receiver in the deposit and henceforth we will keep this simplification.
We can instantiate $f$ as the discrete log one-way function that maps $x$ into $g^x$.
This has also the advantage that one can provide efficient off-chain proofs of liquidity, that is one can show ownership of a certain amount of coins corresponding to a deposit tagged with value $y=g^x$ by proving knowledge of $x$ without revealing $x$ and this can be done by just using a simple non-interactive Schnorr's proof of knowledge.
The drawback is that you would reveal the sender.
Can we do better and also hide the sender among e.g. two senders?
The answer is positive. It is known that sigma protocols (from which non-interactive Schnorr's proof of knowledge is derived) can be composed so that, given two values $y_1=g^{x_1}$ and $y_2=g^{x_2}$, one can prove knowledge of $x_1$ OR $x_2$ without revealing whether the witness used is $x_1$ or $x_2$ (precisely this is a non-interactive zk proof of knowledge of the discrete log in base $g$ of either $y_1$ or $y_2$). This proof system has complexity both for the prover and verifier of approximatively the double of a standard Schnorr's proof so it is extremely efficient.
In our case the receiver can choose two deposits made by different senders. These two deposits are tagged with two different values $y_1=g^{x_1}$ and $y_2=g^{x_2}$ that will be used for the disjunctive proof.
Can we use this technique on-chain to make a withdrawal so as to hide the sender among e.g. two possible senders which sent to the contract the same amount of coins?
The issue is that we need a nullifier to avoid a double withdrawal.
This issue can be solved in the following way.
The sender encrypts under the public key of the receiver two random values $x,z$ and publishes this ciphertext along with a value $g^x\cdot h^z$ for known public bases $g,h$.
A standard withdrawal requires to send to the contract both $x$ and $z$.
However, if the receiver wants to hide the sender among two senders can do the following.
Suppose that there are two deposits (for the same amount) corresponding to values $A_1=g^{x_1}\cdot h^{z_1}$ and $A_2=g^{x_2}\cdot h^{z_2}$ and suppose that the senders of these two deposits are different. The receiver only knows w.l.o.g. $x_1,z_1$ but not $x_2,z_2$ and wants to be able to withdraw while hiding which of the two witnesses he knows.
The receiver can send to the contract just $z_1$, the contract computes $A_1'=A_1/h^{z_1}, A_2'=A_2/h^{z_1}$ so that $A_1'=g^{x_1}$ and $A_2'=g^{x_2}\cdot h^{z_2-z_1}$.
Now the sender gives a nizk proof of knowledge of the fact that he knows the discrete log in base $g$ of either $A_1'$ or $A_2'$. Moreover the contract puts $z_1$ into an hash table.
The withdrawal is successful only if $z_1$ was not in the hash table before and the nizk proof of knowledge is accepted. It can be seen that, assuming discrete log and random oracles, only who knows either $x_1$ or $x_2$ can forge valid proofs and can invalidate the nullifier only once and moreover the proof is zero-knowledge.
In this way, the receiver can withdraw only once and can hide the receiver among 2 (generalizable to $m$) possible receivers.
Recent works (e.g. [Goel et al.](https://eprint.iacr.org/2021/422.pdf)) show that the communication complexity of disjunctions of Schnorr's proofs can be made sublinear so making feasible to extend the idea to achieve $1$ out of $m$ privacy.
The idea can be summarised as follows:
- All firsts messages can be committed using a commitment scheme with the property that is binding for only $1$ out of $m$ positions and hides this position.
- The third message of the real instance (the one for which the prover knows the witness) can be recycled over all other instances since a Schnorr's protocol has a transcript that can be simulated from *any* third message and challenge.
- Given a third message and challenge the simulator is deterministic, so all first messages can be computed by the verifier. Hence, the prover can reveal the randomness used to commit and the verifier can use it to check consistency of the commitment.
We believe that the extension with $1$ out of $m$ privacy for off-chain proofs of liquidity may not present legal issues since this does not result in any coin mixing and being able to prove to a third party ownership of personal assets without revealing their source is a personal right.
### Succint group deposits
Suppose an employer wants to make a deposit for its $N$ employees e.g. on a monthly basis.
The trivial way requires $N$ transactions or a single transaction of length $\Omega(N)$.
We propose an approach with deposits and withdrawals of constant communication and GAS cost and supports proofs of [missed-payment](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Proofs-of-missed-payment-for-succinct-deposits).
Suppose for simplicity that each employee must be paid with single coin (this can be generalized as we will see [later](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Depositing-different-amounts-of-coins-for-each-employees)) and that the employer has a *pool* at the Bank3 identified by some identifier $id$.
We suppose the availability of powers of tau parameters of the form $h_i=g^{\tau^i},i=1,\ldots, N$ and we assume to be in a bilinear group setting (for simplicity a symmetric one).
Each month the generic employee $j\in [N]$ of the company computes $y_j=Hash(sig_j)$, where $sig_j$ is a signature of $id$, and a string representing the month.
The hash can optionally include the address which the employee wants withdraw the coin from; if the address is not specified the employee will need a commit and reveal approach or timelock encryption to tackle front-running attacks.
Moreover we assume that $sig_j$ is de-anonymized from its public key, for instance we can replace $sig_j$ by the hash of the signature itself.
The generic employee $j$ sends $y_j$ to the employer and each other employee (this communication occurs off-chain or on an L2 chain).
The employer can then compute the short commitment $\alpha=g^{\prod_{i=1}^N (y_i+\tau)}$ using the values $h_i$'s.
When the generic employee $j$ wants to withdraw $1/N$ coins, he can compute $w_j=g^{\prod_{i=1}^N (y_i+\tau)/(y_j+\tau)}$, and send to the smart contract $w_j$ and $sig_j$.
The smart contract checks the pairing equation:
$e(w_j,g^{y_j}\cdot h)=e(\alpha,g)$. This convinces the smart contract that $y_j$ is one of the originally committed values. Finally, the smart contract checks whether $sig_j$ is the correct pre-image of $y_j$ along with the given identifier, month and the optional address if specified (in this case the contract must also check whether this address corresponds to the sender of the transaction).
If all checks are satisfied and $y_j$ was not already in an hash table the withdrawal is successful and $1/N$ coins are sent to the sender of the transaction and $y_j$ is added to the hash table so as to prevent future double spending.
Observe that the signatures here are never verified; they are just used as mean for an arbitrary employee $j$ to retrieve all his pre-images in a user-friendly way without storing all of them; this is similar to the [handshake](https://hackmd.io/q4RHSYE6Tb6fRqgPIML9QA?both#Handshake-variant-for-Wallets) variant. We will later show variants in which signatures are verified to achieve additional properties.
#### Proofs of liquidity for succinct deposits
The previous system may be slightly changed so to enable efficient proofs of liquidity off-chain.
Bob can compute $y_j=Hash(g^{Hash_2(sig_j)})$, where $Hash_2$ is a random oracle that maps into the scalar group of $g$ (for simplicity we omitted the identifier from the outer hash).
Then, to provide proofs of liquidity to a verifier, Bob sends the pre-image $z_j=g^{Hash_2(sig_j)}$ of $y_j$ to the verifier who performs the same checks as in the previous smart contract. If such checks pass then Bob and the verifier engage in an additional interactive Schnorr's proof of knowledge in which Bob aims at convincing the verifier of knowledge of the discrete log in base $g$ of $z_j$.
Observe that if this modified system is adopted, the the smart contract must be also changed so as to check a similar Schnorr's proof but in non-interactive form.
This non-interactive Schnorr's proof is such that that the Fiat-Shamir's challenge is computed as hash of the first message, statement and address so as to effectively bind the proof to the specified address and avoid front-running attacks. Observe that, due to these changes, the employer can withdraw from any address by including this address in the Fiat-Shamir's challenge and not in the outer hash.
#### Proofs of missed payment for succinct deposits
As previously discussed, the signatures in our succinct deposit system are never verified.
We can change the system as follows. Firstly, we assume that all employee's public keys are registered in the smart contract (this takes space $O(N)$ but it is done only once for all future deposits and withdrawals).
Now we point out that our basic succinct deposit system (similar considerations hold for the improved systems supporting proofs of liquidity) can be seen as a Nguyen's accumulator which is known to additionally supports proofs of non-membership.
Then, an employee $j$ can send to the smart contract (or an external verifier) his index $j$, the signature $sig_j$ of the identifier and given month that is the pre-image of the value $y_j=H(sig_j)$, and a proof that the value $y_j=Hash(sig_j)$ is *not* included in the succinct deposit.
The smart contract (or an external verifier) checks the non-membership proof and that $sig_j$ is a valid signature with respect to the public key of employee $j$.
This convinces the smart contract (or an external verifier) that the employee $j$ has *not* been paid.
#### Depositing arbitrary amounts of coins for each employee
A limitation of all previous systems is that the employer deposits one coin and each of the $N$ employees can withdraw $1/N$ coins.
We can remove this limitation as follows.
For our basic system the pre-image of the value $y_j$ additionally includes the amount of coins for the employee $j$ and is required the preimage to also include the address from which the employer $j$ will withdraw the coins. The employee $j$ in this case will need to send the preimage of $y_j$ to the employer so that the employer can verify that the employee $j$ is not computing $y_j$ for an higher quantity of coins.
For our system supporting proofs of liquidity, the employee $j$ can send $z_j$ to the employer who can compute $y_j$ as hash of $z_j$, the month and identifier and the quantity of coins directed to employee $j$. Note that, even knowing the pre-image of $y_j$, the employer cannot withdraw on behalf of the employee since withdrawal requires a non-interactive Schnorr's proof computed with the discrete log in base $g$ of $z_j$ that only employee $j$ knows.
#### Group anonymity
In all previous systems the signatures are actually not verified on-chain.
(As an exception we proposed to verify signatures in proofs of missed-payments as means to just record on-chain that a given employee has not been paid but the following would be suitable as well.)
We can replace standard digital signatures with group signatures (e.g. Boneh-Boyen-Schcham).
Recall that it is responsibility of the employer to include in the group deposit all employees and to prevent double payments but this can be done using the traceability property of group signatures, that is the employer can notice whether an employee $j$ tries to submit more than one signature.
Moreover, in this way the withdrawal transaction hides (to every party except the employer) the specific employee associated with the operation.
For proofs of missed payment, the drawback is that an employee who has not been paid can record on-chain that some of the employees has not been paid but cannot disclose his/her identity on the group.
## Implementation
An implementation of the basic Bank3 systems can be found [here](https://github.com/vincenzoiovino/bank3) and a demo of the identity-based features can be found [here](https://github.com/vincenzoiovino/LoI.SmartContracts/tree/975b78237d8f5d35bc6867fe8861a59aaa61fb03).