Transactional privacy with Zeth¶
The decentralised nature of blockchain systems — like Autonity Ledger Systems — and the need for system validators to access transaction details in order to keep the system secure (i.e. reach consensus over a valid state), raise the following question: is it possible to hide the details of transactions processed by the distributed ledger, while preserving its initial security guarantees?
Building on years of research, the Zeth protocol answers this question in the affirmative by proposing a variant of Zerocash that works on top of smart contract enabled blockchains such as Ethereum and Autonity.
This user guide documents the research-quality reference implementation of the protocol and provides all the necessary steps to carry out privacy-preserving transactions on Autonity.
Warning
We gently remind the reader that this user guide documents a research-quality piece of code. As such it is not yet suitable to be used in production environments!
Protocol overview:
The Zeth protocol uses efficient non-interactive zero-knowledge proof systems called zk-SNARKs in order to generate cryptographic proofs — for each transaction — showing that transactions are compliant with the systems' rules (i.e. no transaction is double-spending funds, no value is created etc.) without exposing the transaction details.
While Zeth is extensively documented (see References), we briefly describe the main ideas behind the protocol, and invite the interested reader to consult the referenced documents for further details on the protocol.
Zeth implements a private payment mechanism by running a mixing smart contract on which members of the Autonity network, wanting to transact privately, deposit their funds in the form of notes. Being structured pieces of data (with an owner, value etc.), Zeth notes can then be spent by their owners in order to create new ones (for potentially different users). This ability to spend notes to create new ones — similarly to UTXO-based blockchains — allows users to transact with each other.
While no restriction is set on the value of notes (e.g. we can have notes of value 0.00001
and/or 9990000999
if users want to), the current protocol parameters require that users spend at most two input notes to create at most two output notes in every single Zeth transaction. Moreover, it is necessary for the transaction to be balanced (i.e. the sum of the input values needs to be equal to the sum of the output values) to make sure that no value is created by that transaction. In brief, "note ownership" here is defined by knowledge of a "secret key" associated to a "public key". Anyone wanting to spend their notes needs to use their "secret key" to do so, while transferring funds requires to use the recipient's "public key" to derive the new notes. (In the following this "public key" is referred to as the Zeth payment address, while the "secret key" will be called the Zeth private address.)
All these checks — along with many more — are cryptographically enforced by requiring users to generate a zk-SNARK for each of their transactions. This zero-knowledge proof of computational integrity is then sent on-chain, certifying that the transfer carried out satisfies all the security checks required for the protocol to be secure.
Once notes are spent, and new ones are created, the details of the newly created notes (i.e. their value etc.) are encrypted with the recipient's public key (in a way that protects his anonymity against other network members) and sent to the chain along with the zero-knowledge proof. Upon receipt of the zero-knowledge proof and encrypted data, the Zeth smart contract verifies the proof (to make sure that the transfer is compliant with the system's security rules — and rejects the transfer otherwise), and broadcasts the encrypted data if the proof is deemed valid. Broadcasting the encrypted data allows users to "scan" the blockchain and try to decrypt the data broadcast by the smart contract. In this way, users can discover any transfers for which they are the recipient. This mechanism protects the recipient's anonymity.
All in all, Zeth can be considered as a "privacy preserving ledger on top of Autonity" allowing to carry out payments. As such, not only Zeth transactions hide the amount transferred and the recipient, but using Zeth also hides one's overall wealth on the blockchain. As the total value of unspent Zeth notes can only be retrieved by the notes' owner (other network participants do no know if/when a Zeth user has received Zeth notes), only partial information about users' balances is exposed via the Autonity account balance which is publicly accessible via the blockchain state.
Software overview:
The image below represents the various software components involved in Zeth, as well as a high level run-though of the protocol.
In short, Zeth relies on three pieces of software:
- The
zeth
client: Acts as a wallet that manages the Zeth secrets of the user (Zeth private address, transfer details etc.). This component interacts with both the blockchain and theprover_server
, and provides a Command Line Interface (CLI) to receive and process user inputs. - The
prover_server
: This piece of software receives the (private) details of a transfer from the wallet, and generates the associated zero-knowledge proof and cryptographic commitments. The received zero-knowledge proof and commitments are then sent on-chain, along with the encrypted payment details, to be processed by the Zethcontracts
. - The Zeth
contracts
: Set of smart contracts deployed on the blockchain system that are used to:- verify the zero-knowledge proof to assess the validity of the transfer (without knowing the underlying secret data)
- keep track of the cryptographic commitments
- communicate received payments to the recipient(s) via an encrypted broadcast emulating a confidential receiver-anonymous channel
Importantly, both the client zeth
and prover_server
are run on the user machine. The smart contracts are deployed to and executed on the blockchain.
In the following you will find all the instructions to run the Zeth software stack and execute privacy-preserving asset transfers on the Autonity Bakerloo testnet.
Info
In order to make this tutorial easier to follow, we make use of the zeth_helper
CLI tool, which performs some useful operations on an Ethereum-like system like Autonity. We will use it throughout this documentation to make sure your environment is properly configured. Importantly however, this tool is only here to provide additional help, it is not part of the core Zeth stack, and it is not suitable to be used in production environments.
As this tool is only here to help you through this documentation, feel free to ignore the zeth_helper
commands if you already are an Autonity veteran!
Assets supported:
Zeth can be used to transact with a wide class of digital assets. In fact, Zeth can be used to either:
- Transact Autons: Zeth can be used to transfer AUT on Autonity.
- Transact smart contract defined tokens: Zeth can be used to transfer any ERC20/ERC223 tokens.
Roadmap
ERC777 token transfers are not yet supported, but enabling their support is part of our Roadmap. Supporting this token standard will further widen the domain of applications of Zeth
Prerequisites¶
System requirements
This user guide primarily targets x86_64
Linux and macOS platforms. While we use docker
extensively in the following sections, some instructions may not be supported on different systems. As such, we recommend using virtualization techniques (VMs etc.) to emulate a compliant system architecture if needed
Before proceeding, please note that the following tools are used throughout this documentation. Users should ensure that they are correctly installed at the given versions:
Once the system complies with all the requirements above, fetch the repository by:
- Using
git
to fetch the source code from Githuborgit clone git@github.com:clearmatics/zeth.git cd zeth
- Using
wget
to fetch the last release of the software# See releases: https://github.com/clearmatics/zeth/releases wget https://github.com/clearmatics/zeth/archive/v0.5.tar.gz # Verify the checksum shasum v0.5.tar.gz # Must return: a95ad017eddf8c578cf37e73892647f2cb1a0d63 v0.5.tar.gz # Decompress the received archive to a directory named "zeth" mkdir zeth && tar xf v0.5.tar.gz -C zeth --strip-components 1
Once in the Zeth repository, set up your environment by running:
. ./setup_env.sh
Configure and start the prover server¶
Below, we provide the commands to start the prover_server
in a docker container. The interested reader may want to read the project's README to find out more about how to run this piece of software natively on a x86_64
Linux or macOS system.
For the zero-knowledge proofs to be generated and verified in Zeth, it is necessary to generate a keypair. This keypair must be generated in a secure way to make sure that the system remains secure. While we have implemented a multi-party computation protocol to generate the Zeth keypair securely, we include below a keypair that we will use throughout this documentation.
To download the keypair, click here and here. Then save the files in the zeth
repository you fetched at the previous step, and run the following commands:
cd $ZETH && ./scripts/recover_keypair
Here $ZETH
is the environment variable that contains the path to the zeth
repository on your machine (it is set by the setup_env.sh
script above). The recover_keypair
script combines the keypair files, decompress the keypair into the $ZETH/zeth_setup
directory and deletes the fetched archives.
Make sure that the keypair hash digest returned by the script is: 80be1a34bd4e7c03adb7de8e5e9d3a5ee81b062e zeth_setup/keypair.bin
Warning
While we have generated this keypair honestly, please do not use it in production systems. As we do not want you to trust us, we have implemented a Multi-Party Computation (MPC) protocol to securely (and collectively) generate a keypair that can be used for real-life scenarios
We assume that all commands below are run in the zeth
repository (the path in the $ZETH
variable).
-
Zeth-prover image (built from
Dockerfile-prover
):docker pull clearmatics/zeth-prover:0.5 # Verify the checksum docker images clearmatics/zeth-prover:0.5 --digests --no-trunc # The returned image ID must be: sha256:d911e3f4cd57c3327cbca9584d39ec4b9bbe0eb0d1b6f49cfce1c1e582351c7d
-
Start the Zeth prover and use the keypair fetched at previous steps:
docker run --rm -ti -p 50051:50051 \ -v "$(pwd)"/zeth_setup:/root/zeth_setup/ \ --name prover_server clearmatics/zeth-prover:0.5 \ prover_server
Info
If you wish to start the container in "daemon" mode (i.e. start the process in the background), add the --detach
flag to the command above. You can then see the running containers by running docker ps
Using the Zeth client¶
Warning
As research-grade software, the Zeth wallet should not be relied upon to manage secret data in a secure way. Do not use it with any data that secures real assets (such as real-life Autonity secret keys)
The Zeth client is a set of simple tools, accessible via a single zeth
command, providing deployment and very basic wallet functionalities. It must be executed in a directory containing configuration data for the network (i.e. prover_server
RPC endpoint, Autonity node RPC endpoint, Zeth mixer contract address, etc) as well as public and private data for the current Zeth user (Autonity and Zeth address details, Zeth notes, etc).
The commands below contain instructions to setup client directories. It is possible to create multiple virtual users on a single machine by setting up multiple client directories. This is an effective way of experimenting with the system, to send and receive funds. The client directories are self-contained so that the zeth
command runs in the context of the current Zeth user and is separated from any other virtual users on the system.
Setup the client and install dependencies¶
Enter the client
directory in the Zeth repository, and setup the project:
cd client
python3 -m venv env
source env/bin/activate
make setup
Activating the virtualenv
While the virtualenv is active (indicated by the (env)
prompt prefix), the zeth
command will be available on the command line. To enter the virtualenv from a new shell, use source $ZETH/client/env/bin/activate
After running these commands, all the wallet's functionalities are available as subcommands in the zeth
CLI. Several example commands are provided below. For more information and a full list of commands and available options, please run zeth --help
.
Autonity accounts
The following commands will assume that the user has control of a funded Autonity account.
We recommend that users run the script zeth_helper eth-gen-address
to generate a new Cryptographic IDentity (CID) for each Zeth user, (stored unencrypted in the client directory as eth-private-key
and eth-address
). This new address can then be funded from a pre-existing Autonity account and used for experimenting with Zeth, without reference to the original Autonity account. Contact the Clearmatics team to receive funds to an Autonity account
Deploy Zeth to the testnet¶
Deployers only
This section is only relevant for Zeth contract deployers. If you want to use an existing Zeth instance jump here
-
Create the deployer's client directory, create the client's keys, and initialise it for the Autonity Bakerloo testnet:
mkdir deployer cd deployer zeth_helper eth-gen-address
-
Create a file
eth-network
in the deployer directory, by running the following command, and making sure to replace<rpc-endpoint>
by the RPC endpoint of the node (on the Autonity Bakerloo testnet) you would like to connect to:zeth_helper eth-gen-network-config autonity-bakerloo \ --eth-rpc-endpoint <rpc-endpoint>
The command will create the following eth-network
file:
{
"name": "autonity-bakerloo",
"endpoint": "<rpc-endpoint>"
}
Network configuration and address files
As described above, zeth_helper eth-gen-address
creates files eth-private-key
and eth-address
holding the Autonity private key and address for the client. The network configuration file eth-network
holds information about the Autonity network and how to connect to it (additional network configuration options can be used to pass custom TLS certificates for instance. For more details, please run zeth_helper eth-gen-network-config --help
). Further invocations of the client use this file to query the network and submit transactions
-
Fund the deployer's Autonity address (contained in the file
eth-address
). -
Compile and deploy the contracts:
zeth deploy
Using Zeth with an ERC token
To use Zeth for ERC tokens transfers, please make sure that the ERC token contract you would like to use is already deployed on Autonity, find its address, and add the following flag to the deploy
command above --token-address <your-token-address>
. For further details, see the usage zeth deploy --help
- Make the instance file (
zeth-instance
) public, or share it with future users of the contract. This file contains the ABI of the contract, as well as its address on the Autonity network and will be used to configure the wallet of the contract's users.
Zeth operations¶
In the following, we list the various functionalities of the zeth
wallet, and finish each sub-section with a simplified example. All examples are linked together and provide a more illustrative approach to the Zeth protocol. To that end, we will use the now-famous Alice, Bob and Charlie trio to illustrate the zeth
wallet functionalities.
Info
Run zeth --help
to see all the functionalities of the zeth
CLI
Create a new Zeth user¶
New Zeth users only
This section is only relevant to new Zeth users. If you already have a Zeth address, then jump to the next step
-
Create a user directory to contain the client configuration and state:
mkdir <your-name> cd <your-name>
-
Initialise the client to point to the correct network and Zeth mixer instance:
- Create the
eth-network
file, as for the deployer, by running the following command and replace<rpc-endpoint>
by the RPC endpoint of the node (on the Autonity Bakerloo testnet) you would like to connect to:zeth_helper eth-gen-network-config autonity-bakerloo \ --eth-rpc-endpoint <rpc-endpoint>
- Copy
zeth-instance
shared by the contract deployer:cp <path-to-zeth-instance-file> .
- Create the
Note: The Bakerloo testnet comes with a set of pre-deployed Zeth smart contracts. If you wish to interact with these, please download the testnet zeth-instance
file, by running:
wget https://bakerloo.autonity.network/protocol-suite/assets/zeth-instance
# Verify the checksum
shasum zeth-instance
# Must return: a9df6a68b231ee93bc0dfc80eb95949ad4ae8097 zeth-instance
What is the instance file?
The instance file contains the ABI of the contract as well as its address on the Autonity network. It will be used by your Zeth wallet to point to the right contract on the network when carrying out Zeth transactions
- Generate an Autonity address for the user:
zeth_helper eth-gen-address
and fund the address contained in the file eth-address
.
- Generate a Zeth address:
zeth gen-address
What is a Zeth address?
Your Zeth address will be written unencrypted in two files: zeth-address.priv
and zeth-address.pub
. The pub
file is intended to be shared publicly, or sent to people who may be willing to transact with you. In short, this address is the "payment address" containing two public keys that other users will use to send you funds privately. The priv
file, however, represents the "private address" and must be kept secret. It contains two secret keys that will enable you to know when you receive funds from someone, and manipulate them. For more information on the Zeth address, please refer to Section 1.4 of the Zeth protocol specifications
- Share your Zeth "payment address" (
zeth-address.pub
) with parties willing to transact with you, and/or receive Zeth payment addresses from other parties you wish to transact with.
Example - Chapter 1
Charlie is a tech-savvy person, always trying new things and eager to impress his friends Alice and Bob. His new endeavor is to initiate his friends to Zeth in order to show them how to do privacy-preserving state transitions on Autonity. To that end, Charlie has deployed the Zeth contracts on the Autonity Bakerloo testnet, and has published the zeth-instance
on his personal webpage (at https://charlie-tech-personal.mock/zeth-instance
). Along with this file, Charlie listed a few testnet miner nodes IPs — one of which being 172.16.212.67
, exposing an Autonity RPC endpoint on port 8545
After being convinced by her friend Charlie, Alice decides to give Zeth a try. To that end, she types the following commands in her terminal:
Alice
(env) $ mkdir alice && cd alice
(env) $ zeth_helper eth-gen-network-config autonity-bakerloo --eth-rpc-endpoint 172.16.212.67:8545
(env) $ wget https://charlie-tech-personal.mock/zeth-instance
(env) $ zeth_helper eth-gen-address
(env) $ zeth gen-address
Finally, she publishes her payment address on her charity website (at https://alice-charity.mock/zeth-address.pub
) and writes a message inviting donations to be made using her Zeth payment address
After some discussions, Charlie also convinced Bob to use Zeth with him and Alice. Bob followed this tutorial using Charlie's help, but decided to connect to his testnet node — 172.16.217.125
— instead
The zeth mix command¶
Once the client has been set up as described above, Zeth transactions can be issued with the zeth mix
command. This is a generic command that supports any combination of:
-
deposits of public funds (i.e. deposit Autons from your Autonity account or ERC20/223 tokens) onto the Zeth mixer contract, creating new Zeth notes (potentially created for other users)
-
transfers of funds via "pouring" the value of sender-owned Zeth notes to newly created Zeth notes (potentially owned by other users)
-
withdrawal of funds from Zeth (i.e. recover Autons or ERC20/223 tokens)
The examples below illustrate some simple operations. For further information, see the output of zeth mix --help
, and the references given at the end of this section.
Note that the zeth mix
command requires a running prover_server
in order to generate the zero-knowledge proofs that are included in the blockchain transactions.
The proof generation will take several seconds, after which the Zeth transaction will be sent to the blockchain.
Depositing funds¶
Depositing funds on the mixer contract is done by passing the amount to deposit to the --vin
flag of the zeth mix
command:
zeth mix --out zeth-address.pub,2 --vin 2 --wait
zeth-address.pub
is the the user's Zeth payment address.
The type of asset manipulated depends on the asset used during the deployment of the Zeth contract. Depositing Autons on the Zeth contract will only work if your Autonity balance is higher than the amount deposited. Depositing ERC20/223 tokens, however, will also require that the Zeth contract is allowed to transfer at least the amount of tokens you deposit. If you don't know how to set the contract's allowance, you can use zeth_helper token-approve
(use --help
to see the usage).
Specifying Zeth public addresses
Here the value zeth-address.pub,2
of the --out
flag is the filename of the user's public key who will own the new note of value 2
.
The address data itself (i.e. the human-readable content of zeth-address.pub
) can also be specified here. This allows Zeth addresses to be exchanged as plain text and pasted into files or onto the command line directly. If the target Zeth payment address is omitted (for example, --out 2
), it defaults to the sender's own public address (written in the file zeth-address.pub
in the current directory)
Asynchronous operations
The --wait
flag above will cause the client to wait for the transfer transaction to be mined on the Autonity network. Where the --wait
flag is omitted, the sync command, described below can be used to obtain the latest state of the network and reflect this in the client's local data
Example - Chapter 2
After creating his Zeth address and initialising his wallet (as in the previous steps of this tutorial), Bob decides to convert most of his Autonity account balance of AUT into Zeth notes. Having 20 AUT in his balance, he decides to deposit 19 AUT on the Zeth contract, and keep 1 AUT in order to pay the gas cost of the various smart contracts he will call from this account in the future. Additionally, Bob wants to split his 19 AUT into two notes of respective value 2 AUT and 17 AUT
As such, Bob runs the following command:
Bob
(env) $ zeth mix \
--out zeth-address.pub,2 \
--out zeth-address.pub,17 \
--vin 19 --wait
Listing unspent Zeth notes¶
The set of (unspent) notes owned by the current user can be listed as follows:
zeth ls-notes
# b1a2feaf: value=2, addr=0
This command will refer to the notes by using their truncated commitment values (b1a2feaf
here).
Example - Chapter 3
Some time after depositing his funds, Bob sees the two Zeth notes he created.
Bob
(env) $ zeth ls-notes
bf940eaf: value=2, addr=0
feaeacb9: value=17, addr=1
Transferring assets between Zeth users¶
In order to spend notes to transfer funds, users need to spend one or two of their Zeth notes in order to create new notes (one — or both — being owned by the recipient). This can done by using the --in
and --out
flags of the zeth mix
command. These flags respectively take the input notes to spend, and the recipients and values of the output notes to create:
zeth mix \
--in b1a2feaf \
--out <peer-payment-address>,0.5 \
--out <my-payment-address>,1.5 \
--wait
Here, <peer-payment-address>
is the Zeth payment address of the recipient, while <my-payment-address>
is the sender's Zeth payment address (in zeth-address.pub
).
Spending Zeth Notes
Zeth notes must be fully consumed when they are spent. In the example command above, the note b1a2feaf
(with value 2) is split, with 0.5 being sent to the peer as a new Zeth note, and 1.5 returned to the user (again, as new Zeth note). When the transaction is successfully added to the blockchain, the Zeth note b1a2feaf
will be locally marked as "spent" and can no longer be used (trying to double-spend this note will violate some cryptographic checks on the Zeth smart contracts leading to a rejection of the transaction)
Example - Chapter 4
Eager to surprise and encourage his friend Alice (who is trying to raise funds for her charity), Bob decides to donate 7 AUT to her. Fortunately, he fetched her payment address some days ago and added it to his local recipient list (via wget -c https://alice-charity.mock/zeth-address.pub --output-document recipients/alice-payment-address.pub
).
To donate, Bob "splits" his Zeth note feaeacb9
of "face-value" 17 AUT, into one note of value 7 AUT for his friend Alice, and takes the change back to himself via a new note of value 10 AUT:
Bob
(env) $ zeth mix \
--in feaeacb9 \
--out recipients/alice-payment-address.pub,7 \
--out zeth-address.pub,10 \
Bob is very happy, he just gave his friend 7 AUT. Alice has no clue she just received a donation, but she is about to figure this out!
Synchronising with the network¶
Clients must periodically "sync" with the network. During this process, the wallet tries to decrypt the encrypted data broadcast by the Zeth contracts in order to determine if the user received new payments. In the event of a successful decryption, the wallet updates its local state in order to keep track of the newly received funds. This is performed with the zeth sync
command.
In the case of the recipient above, likely output from the zeth sync
command will be of the form:
zeth sync
# SYNCHING blocks (24 - 38)
# NEW NOTE: 21aafa0f: value=0.5E, addr=1
# SYNCED to 38
See the output of zeth sync --help
for further details.
Example - Chapter 5
Having been away for some time, Alice decides to check if she received any donations at all over the past days. To check whether she has received any funds via Zeth, she syncs her wallet with the chain by running zeth sync
. Her wallet scans the chain, tries to decrypt the encrypted messages broadcast by the Zeth contracts, and after some time... Surprise! She received a donation of 7 AUT from someone!
In fact, she now has a Zeth note of 7 AUT, as shown by her wallet:
Alice
(env) $ zeth ls-notes
a7a73eff: value=7, addr=2
Alice is now more motivated than ever to continue her charity project, and hopes to receive more donations in the future.
Withdrawing funds¶
While it is encouraged to keep transferring funds via Zeth and not withdrawing (to improve one's transactional privacy — and minimise information leakages), it is often necessary to withdraw funds from Zeth. In order to do that, users need to spend an input note in order to recover funds publicly. This can be done by using the --vout
flag of the zeth mix
command — that can be used in combination with all other flags presented above, e.g:
zeth mix --in 21aafa0f \
--out <my-payment-address>,0.25 \
--vout 0.25
Example - Chapter 6: The end
After hearing about Zeth, more people decided to join the network and use the protocol. Among them, Eve, a computer retailer. That's perfect, Alice needs to invest in her project and was about to buy one! She can use the Zeth note she received and buy a computer (6 AUT worth) from Eve, and withdraw the rest of her funds in AUT to convert them to fiat and buy a desktop in the nearest shop:
Alice
(env) $ zeth mix \
--in a7a73eff \
--out eve-payment-address.pub,6 \
--vout 1
She is now fully equipped and ready to start to work!
The end.
Advanced commands¶
In the section above, all commands have been introduced one after the other in order to illustrate the various functionalities of the zeth
wallet. Nevertheless, all the flags of the zeth mix
command can be used together to create more complex payment flows. While providing a comprehensive list of such payments is outside of the scope of this documentation, we list a few such commands below as examples, and advise the reader to experiment further with the protocol.
Multiple transfers from public funds¶
# Charlie can pay both Alice and Bob simultaneously from public funds
zeth mix \
--vin 10 \
--out alice-payment-address.pub,0.33 \
--out bob-payment-address.pub,9.67 \
Multiple transfers from Zeth notes¶
# Charlie can pay both Alice and Bob simultaneously from owned notes
zeth mix \
--in aef79ef2 \
--in fff7bef7 \
--out alice-payment-address.pub,0.33 \
--out bob-payment-address.pub,9.67 \
"Top up" transfer¶
# zeth ls-notes
# aef79ef2: value=2.783, addr=9
# Charlie can "top up" his Zeth notes from public funds in a transfer
zeth mix \
--vin 0.217 \
--in aef79ef2 \
--out alice-payment-address.pub,3 \
and many more...
References¶
For further details and information about the Zeth protocol, please consult:
Finally, additional materials on Clearmatics Research can be found on the Clearmatics Research website.
Help
If you need help, you can:
- Chat to us on Discord
- Submit a support ticket
- Send an email to bakerloo-support@clearmatics.com