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.

PlatformValueExample
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}\zfaceC:\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 in encrypted-balances module.
./target/release/zface tx send -t <RECIPIENT_ADDRESS> -a <AMOUNT>
  • Submit a transaction to call issue function in encrypted-assets module.
./target/release/zface tx asset-issue -a <AMOUNT>
  • Submit a transaction to call asset_transfer function in encrypted-assets module.
./target/release/zface tx asset-send -t <RECIPIENT_ADDRESS> -a <AMOUNT> -i <ASSET_ID>
  • Submit a transaction to call burn function in encrypted-assets module.
./target/release/zface tx asset-burn -i <ASSET_ID>
  • Submit a transaction to call issue function in anonymous-balances module.
./target/release/zface tx anonymous-issue -a <AMOUNT>
  • Submit a transaction to call anonymous_transfer function in anonymous-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.

Hierarchical Deterministic Keys

Open problems

Trusted setup

Linearly scaling computational cost in terms of anonimity set

Limited functionalities for privacy-protecting operations