Git Product home page Git Product logo

anonymous-zether's Introduction

WARNING: The security of this cryptographic protocol has not yet been formally proven. This repository should not be considered suitable for production use.

Anonymous Zether

This is a private payment system, an anonymous extension of Bünz, Agrawal, Zamani and Boneh's Zether protocol.

The authors sketch an anonymous extension in their original manuscript. We develop an explicit proof protocol for this extension, described in the technical note AnonZether.pdf. We also fully implement this anonymous protocol (including verification contracts and a client / front-end with its own proof generator).

Thanks go to Benedikt Bünz for discussions around this, as well as for the original Zether work. Also, Sergey Vasilyev's range proof contracts served as a starting point for our Zether verification contracts.

High-level overview

Anonymous Zether is an private value-tracking system, in which an Ethereum smart contract maintains encrypted account balances. Each Zether Smart Contract (ZSC) must, upon deployment, "attach" to some already-deployed ERC-20 contract; once deployed, this contract establishes special "Zether" accounts into / out of which users may deposit or withdraw ERC-20 funds. Having credited funds to a Zether account, its owner may privately send these funds to other Zether accounts, confidentially (transferred amounts are private) and anonymously (identities of transactors are private). Only the owner of each account's secret key may spend its funds, and overdraws are impossible.

To enhance their privacy, users should conduct as much business as possible within the ZSC.

We briefly describe the operation of the (anonymous) Zether Smart Contract, following the original Zether paper. Each account consists of an ElGamal ciphertext, which encrypts the account's balance under its own public key. To send funds, Alice publishes an ordered list of public keys—which contains herself and the recipient, among other arbitrarily chosen parties—together with a corresponding list of ElGamal ciphertexts, which respectively encrypt (under the appropriate public keys) the amounts by which Alice intends to alter these various accounts' balances. The ZSC applies these "adjustments" using the homomomorphic property of ElGamal encryption (with "message in the exponent"). Alice finally publishes a zero-knowlegde proof which asserts that she knows her own secret key, that she owns enough to cover the deduction, that she deducted funds only from herself, and credited them only to Bob (and by the same amount she debited, no less); she of course also demonstrates that she did not alter those balances other than her own and Bob's. These adjustment ciphertexts—opaque to any outside observer—conceal who sent funds to whom, and how much was sent.

Users need never interact directly with the ZSC; rather, our front-end client streamlines its use.

Our theoretical contribution is a zero-knowledge proof protocol for the anonymous transfer statement (8) of Bünz, et. al., which moreover has appealing asymptotic performance characteristics; details on our techniques can be found in the technical report. We also of course provide this implementation.

Anonymous Zether is not yet feasible for use in the Ethereum mainnet (see the technical report for gas use details). However, after Istanbul, things will be much better.

Quickstart

To deploy the ZSC (Zether Smart Contract) to a running Quorum cluster and make some anonymous transfers...

Install prerequisites

  • Yarn tested with version 1.17.3
  • Node.js tested with version v12.9.1

Setting things up

  • Spin up a Quorum cluster (e.g., follow the steps of the 7nodes example).
    • For the Node.js example in this project to work, WebSockets need to be enabled when starting up geth / Quorum (i.e., use the flags --ws, --wsport 23000, --wsorigins=* on your first geth node).
    • The code as currently written only supports IBFT consensus (with --istanbul.blockperiod 1!). The reason is because Raft reports block time differently (in nanoseconds, as opposed to milliseconnds), an idiosyncracy which interferes with epoch measurements. We don't plan on maintaining support for Raft at this time.
  • In the main anonymous-zether directory, type yarn.

Run the Node.js demo

The Node.js example project in this repo will first deploy the necessary contracts: ZetherVerifier.sol, BurnVerifier.sol, CashToken.sol, and finally ZCS.sol (which is dependent on the previous contracts).

Having done this, the Node.js application will fund an account, add a "friend", and make an anonymous transfer.

Simply navigate to the main directory and type node packages/example.

Detailed usage example

Let's assume that Client has been imported and that all contracts have been deployed, as in packages/example/index.js#L12-L19. In four separate node consoles, point web3 to four separate Quorum nodes (make sure to use WebSocket or IPC providers); for each one, execute

> var home
> web3.eth.getAccounts().then((accounts) => { home = accounts[accounts.length - 1]; })

to assign the address of an unlocked account to the variable home.

In the first window, Alice's let's say, execute

> var alice = new Client(deployed, home, web3)
> alice.initialize()
Promise { <pending> }
Registration submitted (txHash = "0x3420c7ec482391ddaf349742bacc30ac26a5eba92dd1828f95499c5909c572b3").
Registration successful.

and in Bob's,

> var bob = new Client(deployed, home, web3)
> bob.initialize()

Do something similar for the other two.

The two methods deposit and withdraw take a single numerical parameter. For example, in Alice's window, type

> alice.deposit(100)
Initiating deposit.
Promise { <pending> }
Deposit submitted (txHash = "0xa6e4c2d415dda9402c6b20a6b1f374939f847c00d7c0f206200142597ff5be7e").
Deposit of 100 was successful. Balance now 100.

If this doesn't work, make sure that your deployments, as well as your minting and approval operations, went through properly.

Now, type:

> alice.withdraw(10)
Initiating withdrawal.
Promise { <pending> }
Withdrawal submitted (txHash = "0xd7cd5de1680594da89823a18c0b74716b6953e23fe60056cc074df75e94c92c5").
Withdrawal of 10 was successful. Balance now 90.

In Bob's window, use

> bob.account.public()
[
  '0x17f5f0daab7218a462dea5f04d47c9db95497833381f502560486d4019aec495',
  '0x0957b7a0ec24a779f991ea645366b27fe3e93e996f3e7936bdcfb7b18d41a945'
]

to retrieve his public key and add Bob as a "friend" of Alice, i.e.

> alice.friends.add("Bob", ['0x17f5f0daab7218a462dea5f04d47c9db95497833381f502560486d4019aec495', '0x0957b7a0ec24a779f991ea645366b27fe3e93e996f3e7936bdcfb7b18d41a945'])
'Friend added.'

You can now do

> alice.transfer("Bob", 20)
Initiating transfer.
Promise { <pending> }
Transfer submitted (txHash = "0x4c0631483e6ea89d2068c90d5a2f9fa42ad12a102650ff80b887542e18e1d988").
Transfer of 20 was successful. Balance now 70.

In Bob's window, you should see:

Transfer of 20 received! Balance now 20.

You can also add Alice, Carol and Dave as friends of Bob. Now, you can try:

> bob.transfer("Alice", 10, ["Carol", "Dave"])
Initiating transfer.
Promise { <pending> }
Transfer submitted (txHash = "0x9b3f51f3511c6797789862ce745a81d5bdfb00304831a8f25cc8554ea7597860").
Transfer of 10 was successful. Balance now 10.

The meaning of this syntax is that Carol and Dave are being included, along with Bob and Alice, in Bob's transaction's anonymity set. As a consequence, no outside observer will be able to distinguish, among the four participants, who sent funds, who received funds, and how much was transferred. The account balances of all four participants are also private.

In fact, you can see for yourself the perspective of Eve—an eavesdropper, let's say. In a new window (if you want), execute:

> var inputs = deployedZSC.jsonInterface.abi.methods.transfer.abiItem.inputs
> var parsed
> web3.eth.getBlock('latest').then((block) => web3.eth.getTransaction(block.transactions[0])).then((transaction) => parsed = web3.eth.abi.decodeParameters(inputs, "0x" + transaction.input.slice(10)))

You will see a bunch of fields; in particular, parsed['y'] will contain the list of public keys, while parsed['L'], parsed['R'] and parsed['proof'] will contain further bytes which conjecturally reveal nothing about the transaction.

Keep in mind that there are a few obvious situations where information can be determined. For example, if someone who has never deposited before appears in a transaction for the first time (this was the case of Bob earlier above), then it will be clear that this person was not the transaction's originator. Similarly, if a certain person has performed only deposits and withdrawals, then his account balance will obviously be visible.

More subtly, some information could be leaked if you choose your anonymity sets poorly. Thus, make sure you know how this works before using it.

anonymous-zether's People

Contributors

benediamond avatar zzy96 avatar stubocka avatar jpmsam avatar libby avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.