Introduction
This documentation helps developers understand the core concepts of Zerochain and walks through the steps required to build a Zerochain node and send confidential transactions using Zerochain’s module.
Zerochain is a generic, privacy-protecting layer on top of Substrate. It provides substrate modules and a toolkit for protecting the user's identity and sensitive data that is stored on chain. Zerochain protocol (v1) combines with solutions of the Zether and Zcash toolchain and of course Substrate.
- Zether is a high-level privacy scheme which takes an account-based approach.
- The Zcash toolchain is a Zero-knowledge proving system with elliptic curve operations.
- Substrate is a blockchain layer which provides core components such as P2P networking, database, and a consensus engine.
The first goal of Zerochain is to provide a secure and efficient confidential and anonymous payment protocol for fungible assets. The requirements are that
- Transferred amounts are private.
- Each account balance is private.
- Identities of transactors are private.
Core features of Zerochain are
- Efficient computational cost of zk-proofs and verification.
- Auditability for each account.
- Storage friendly confidentiality from the point of view of both the wallet and blockchain.
More precisely
- In general, computational costs tend to be huge for zero-knowledge proofs. Zerochain uses pre-processing zk-SNARKS which is a kind of ZK proving systems that has low computational cost and small proof size. There are, however, some trade-offs.
- Statements in zk-SNARK are based on the Zether protocol so that computational cost of the proof is less than other privacy-protecting protocols.
- Users can allow auditors to observe account balances by using a viewing key but auditors cannot use the key to spend the user's money.
- Zerochain's wallet doesn't need to run either full node or light client. It can simply send transactions using an RPC API.
- Zerochain is an account-based blockchain so it can avoid UTXO accumulation and minimize storage.
Getting Started
In this section, we will explain how to run Zerochain and send confidential/anonymous transactions.
Installation
Initial Setup
Setup latest rust environment.
curl https://sh.rustup.rs -sSf | sh
rustup update stable
rustup update nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
cargo +nightly install --git https://github.com/alexcrichton/wasm-gc
You will also need to install the following packages:
- Mac:
brew install cmake pkg-config openssl git llvm
- Linux:
sudo apt install cmake pkg-config libssl-dev git clang libclang-dev
Building
Zerochan, then, can be building.
git clone https://github.com/LayerXcom/zero-chain.git
cd zero-chain
./build.sh
cargo build --release
Turotial: Confidential payment
This tutorial will explain the basic confidential transfer on Zerochain. Alice has the encrypted balance of 10,000 coins and sends encrypted 100 coins to you. The encrypted fee will be subtracted from her balance. (By default, a base fee parameter is set to 1.) So, Alice's balance will be 9,899 coins and you will get the 100 coins. All operations are done encrypted by ElGamal encryption and zk-SNARKs.
In this tutorial, we assumed you've already done the all installation explained previous section.
1. Install ZFace
First of all, you need to install ZFace to interact with Zerochain. ZFace is basically a low-level wallet core and cryptographic tools for Zerochain.
cargo build --release -p zface
Then, you can use CLI powerd by ZFace.
2. Wallet creation
Create a new zerochain wallet.
./target/release/zface wallet init
You will then be prompted to enter a wallet password and a initial account name. Please, note carefully the following mnemonic words. They will be needed to recover your wallet.
3. Run Zerochain nodes
Run a Zerochain node in other terminal screen. --dev
flag is for specifying development mode.
./target/release/zerochain --dev
If you want to clear your old chain's history:
./target/release/zerochain purge-chain --dev
4. Interacting with Zerochain
4-1. Transfer initial minted coins to your account
When you initialize your Zerochain, a specific Alice account has initial minted 10,000 coins (of course, it is encrypted). You can transfer the encrypted coins from Alice to your just generated account by debug
command.
./target/release/zface debug send -t <YOUR ADDRESS> -a <AMOUNT>
For example, the following command can transfer 100 coins to 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i
address. The address is depending on your account. Please copy and pasted printed-out address.
./target/release/zface debug send -t 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i -a 100
4-2. Check your balanace
If the transferring coins was done successfully, your account should have 100 coins. You can check the balance by
./target/release/zface wallet balance
You will then be prompted to enter your passoword.
4-3. Confidential payment between your accounts
You also can transfer encypted coins to your other your account by the following commands.
- Create other your account
./target/release/zface wallet add-account
- Check your accounts list
./target/release/zface wallet list
- Change default account to your first account who has 100 coins
./target/release/zface wallet change-account -n <ACCOUNT_NAME>
- Transfer encrypted coins to your new account
./target/release/zface tx send -t <ADDRESS> -a <AMOUNT>
It's Done!
Turotial: Encrypted fungible assets
In this tutorial, we'll exlapin how you can manage your encrypted fungible assets in Zerochan. We provide a special substrate module called encrypted-assets
module in order to mint, burn, and transfer encrypted assets. These assets are encrypted on-chain, so no-one can see the actual amounts without its decryption key. Each assets has an unique asset-id
to be managed as separated assets.
We expect you to install ZFace, create your wallet, and run Zerochain following the section1~3 in this page.
1. Mint 100 encrypted coins
You can mint your encrypted assets by the following commands. The amount is specified 100
and the asset-id is automatically determined as a unique number. You can fetch the asset-id by the event.
./target/release/zface tx asset-issue -a 100
2. Transfer encrypted asset
Let's transfer 20 encrypted-coins to the address 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i
(This address is depending on your wallet account). The asset-id of initial minted assets is 0
, so you need to specify it.
./target/release/zface tx asset-send -a 20 -i 0 -t 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i
3. Check your current balance of encrypted assets
You just transferred 20 assets to other address and are subtracted 1 assets as fee, so you're supposed to have 79 assets.
./target/release/zface wallet asset-balance -i 0
4. Burn encrypted asset
To burn your encrypted assets, just specify the asset-id and then destroy the assets.
./target/release/zface tx asset-burn -i 0
Tutorial: Anonymous payments
In this tutorial, we'll explain how you can send transactions in an anonymous manner. We provide a special Substrate module called anonymous-balances
module. User's coins managed in the anonymous-balances
modules are encrypted in the same way as encrypted-balances
module. To get an anonimous features, more precisely obfuscating features, some dummy addresses are added to a target address set in a transaction, so that an actual recipient address and dummy addresses cannot be distinguishable from the other people perspective.
For following the tutorial, we expect you to already install ZFace, create your wallet, and run Zerochain, see the section1~3 in this page.
1. Mint 100 encrypted coins
You can mint your encrypted coins by the following commands. This issue method isn't anonymous way but confidential way.
./target/release/zface tx anonymous-issue -a 100
2. Send an anonymous transaction
Let's transfer 20 encrypted-coins to the address 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i
(This address is depending on your wallet account). Some dummy addresses are automatically added to the transaction so that other people cannot see where it came from and went to.
./target/release/zface tx anonymous-send -a 20 -t 5DC4kJ84b4KfVyddcFMYfy5skTJWVtxtWRETZo2i4nh8Ao1i
3. Check your current balance
You just transferred 20 assets to other address, so you're supposed to have 80 assets.
./target/release/zface wallet anonymous-balance
ZFace: An interface for interacting with Zerochain
(WIP)
ZFace is a low-level wallet core and cryptographic tools for Zerochain.
In this section, we explained the usage of CLI tools powered by ZFace. The CLI tool has mainly four subcommands which is explained later.
- snark: Operations around zk-SNARKs
- wallet: Operations around wallet
- tx: Operatipons around sending transactions to Zerochain
- debug: Debugging and testing commands
Creating a new wallet
For security reasons, the cryptographic materials are stored encryped by providing a password.
To do this, run:
./target/release/zface wallet init
You will then be prompted to enter a password. This password will be used to encrypt your mnemonics of your wallet. Wallet files are stored in zface directory located in the following path.
Platform | Value | Example |
---|---|---|
Linux | $XDG_DATA_HOME or $HOME/.local/share/zface | /home/alice/.local/share/zface |
macOS | $HOME/Library/Application Support/zface | /Users/Alice/Library/Application Support/zface |
Windows | {FOLDERID_LocalAppData}\zface | C:\Users\Alice\AppData\Local\zface |
Add a account
You can add a new account into your wallet.
./target/release/zface wallet add-account
Show accounts list
It will show your accounts in your wallet.
./target/release/zface wallet list
Change default account
./target/release/zface wallet change-account -n <ACCOUNT_NAME>
Recover a wallet from mnemonic
(TODO)
./target/release/zface wallet recover
You will then be prompted to enter a mnemonic to recover your wallet.
Get balances
- Getting your current balance from
encrypted-balances
module
./target/release/zface wallet balance
- Getting your curernt balance from
encrypted-balances
module
./target/release/zface wallet asset-balance -i <ASSET_ID>
- Getting your curernt balance from
anonymous-balances
module
./target/release/zface wallet anonymous-balance
Setup for zk-proving
Generating a proving key and verifying key of zk-SNARKs.
./target/release/zface snark setup
send
- Submit a transaction to call
confidential_transfer
function inencrypted-balances
module.
./target/release/zface tx send -t <RECIPIENT_ADDRESS> -a <AMOUNT>
- Submit a transaction to call
issue
function inencrypted-assets
module.
./target/release/zface tx asset-issue -a <AMOUNT>
- Submit a transaction to call
asset_transfer
function inencrypted-assets
module.
./target/release/zface tx asset-send -t <RECIPIENT_ADDRESS> -a <AMOUNT> -i <ASSET_ID>
- Submit a transaction to call
burn
function inencrypted-assets
module.
./target/release/zface tx asset-burn -i <ASSET_ID>
- Submit a transaction to call
issue
function inanonymous-balances
module.
./target/release/zface tx anonymous-issue -a <AMOUNT>
- Submit a transaction to call
anonymous_transfer
function inanonymous-balances
module.
./target/release/zface tx anonymous-send -t <RECIPIENT_ADDRESS> -a <AMOUNT>
Manage encrypted assets
- Issue new encrypted assets
./target/release/zface tx asset-issue -a <AMOUNT>
- Send encrypted assets
./target/release/zface tx asset-transfer -t <RECIPIENT_ADDRESS> -a <AMOUNT> -i <ASSET_ID>
- Burn encrypted assets
./target/release/zface tx asset-burn -i <ASSET_ID>
Test for debugging
Print key components
./target/release/zface debug key-init
Send tx for debuggin
./target/release/zface debug send -s <SENDER_SEED> -t <RECPIENT_ADDRESS> -a <AMOUNT>
Print transaction components
./target/release/zface debug print-tx
Confidential Payment
The encrypted-balances module provides a confidential payment module.
In this section, we will explain what is "confidential payment" and how it works.
Overview
On-chain operations
In the basic confidential payment scheme in conf_transfer module, there is one public dispatchable function confidential_transfer
. It takes some parameters such as a zero-knowledege proof, some ciphertexts and addresses.
In this function, mainly three internal functions are called. First one is roll_over
function for pending transfers which is explained later. roll_over
allows us to send transactions asynchronously and protect from front-running attacks. We rollover an account in an epoch when the first message from this account is received, soone message rolls over only one account. To achieve this, we define a separate (internal) method for rolling over, and the first thing every other method does is to call this method.
Second one is validate_proof
function for varifying zk proofs. (For more details: Statements in circuit) Last one is mutating storage to add encrypted coins to recipient's encrypted balance and subtract it from sender's encrypted balance.
Pending transfer
Zerochain uses a pending transfer strategy to prevent from front-running attacks. This attack is that a malicious attacker can watch Alice's transaction and his transaction gets processed first, then Alice's transaction will be rejected because the proof will not be valid anymore. More precisely, Alice's encrypted balance is updated, so public input to validate_proof
parameter is no longer correct.
To solve this problems, we have encrypted_balance
and pending_transfer
mappings to store account's balances on-chain. encrypted_balanace
is a actual balance mapping and pending_transfer
is like a temporary storage in order to store incoming payments.
Let's think a simple case that Alice sends encrypted 5 coins to Bob. The encrypted 5 coins will be stored Bob's pending_transfer
at first, not affect Bob's encrypted_balance
. In the next time when someone sends coins to Bob or Bob sends coins to someone, rollover
function will be invoked and balances are transferred from pending_transfer
map to encrypted_balance
map.
More details in Section 3.1: https://crypto.stanford.edu/~buenz/papers/zether.pdf
Subtracting encrypted fees
Fees are subtracted from sender's encrypted balance based on transaction_base_fee
storage key in the conf_transfer
module.
transaction_base_fee
is set to 1
by default in chain_spec.rs.
Statement in circuit
Circuit implementation can be found here.
(TODO)
Technology
In this section, we will explain core technologies which is used in Zerochain.
zk-SNARKs
(TODO)
Encryption scheme
All transferred amounts and account balances are encrypted in Zerochain, but you have to compute(add or sub) these with encrypted at the time of the payment.
Zerochain achieves it by using the special encryption algorithm called “Additive homomorphic encryption”. As you can guess from the name, it can compute the addition(or subtraction) with encrypted. More specifically, Zerochain uses “Lifted-ElGamal encryption” to get efficient encryption and additive homomorphic property. (You can think it’s like Pedersen commitment in terms of additive homomorphic property, but Lifted-Elgamal is an asymmetric key encryption algorithm, not a commitment.)
Encryption
You can compute the ciphertext like bellow.
ciphertext:
where v: transferred amount, r: pseudorandomness, G: generator point, s: secret key (the corresponding public key: sG)
Decryption
You can decrypt it by using the given ciphertext and secret key.
Then, you realize you have to solve the discrete logarithm problem to get the amount “v”. Practically, “v” would be just a small bits integer (like 32bits) and vG(v=1,2,…) are computed in advance. (On the other hand, the secret key “s” and pseudorandom “r” will be a huge number so that one cannot solve the discrete logarithm.)
The decryption of Lifted-ElGamal is not efficient like this, but we chose it as an encryption algorithm in Zerochain due to the efficient encryption and the good compatibility with zero-knowledge proof.
Additive homomorphic
Let’s think the case the user has encrypted 10 coins as his balance, then is transferred encrypted 5 coins. That is the addition of ciphertext with v = 10 as balance and v’ = 5 as amount.
This is the same form as the ciphertext you see above. You can get the amount “15” by using secret key “s” in the same way. All the additions of ciphertext are computed on-chain at the time of updating the balance.
Key components
These arrows are one-way. For example, you cannot derive a spending key from a decryption key, but you can derive a decryption key from a spending key.
These bunch of keypairs allow us to get a auditability, zk-proofs delegation and hide a signer's identity.
This key components scheme is modified and simplified version of zcash sapling's one to be compatible with Zerochain.
Signing key
Every time you sign a transaction, a re-randomized signing key will be generated so that a signature will be different from the previous one. It helps to make it quite difficult to distinguish the sender's address because the signature of the same sender is no longer same.
Decryption key
A decryption key works as a viewing key which allows only this key's owener to see the encrypted balance which is stored on-chain.
If you pass your decryption key to auditors, they can see your current balance, but cannot spend your coins of course.
Encryption key
Encryption key is a public key can be used to encrypt all transferred amounts and balances.