Giter Site home page Giter Site logo

layerxcom / zero-chain Goto Github PK

View Code? Open in Web Editor NEW
261.0 29.0 47.0 539.88 MB

A privacy-preserving blockchain on Substrate

Home Page: https://layerxcom.github.io/zerochain-book/

License: GNU General Public License v3.0

Rust 99.72% Shell 0.17% Dockerfile 0.11%
substrate zero-knowledge blockchain rust zk-snarks

zero-chain's Introduction

Zerochain

Build Status Gitter


Zerochain is a generic privacy-protecting layer on top of Substrate. It provides some useful substrate modules and toolkit for protecting user's privacy and sensitive data stored on chain. It is designed to get efficient zero-knowledge proving, reduce the on-chain storage cost and bring the flexibility for developing applications.

Have a look at Zerochain Book for usage and more information about using Zerochain.

Status

WARNING: Zerochain is alpha quality software, improvements and fixes are made frequently.

For now, only supported for the PoC of confidential payment inspired by Zether paper.

  • Balance for each account is encrypted
  • Transfer amount is encrypted

More features will be added... 💪💪

Initial Setup

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

git clone [email protected]:LayerXcom/zero-chain.git
cd zero-chain
./build.sh
cargo build --release

Usage and Tutorial

Documented in Zerochain Book.

Related Repositories

Documentations

References

Contributing

  • Feel free to submit your own issues and PRs
  • For further discussions and questions talk to us on Gitter

Maintainers

zero-chain's People

Contributors

ashwhitehat avatar john-light avatar osuketh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zero-chain's Issues

Fix key agreement

Update key agreement process for Ed25519 that is used in substrate key store.
I can not use below one because of lack of adopting Ed25519 algorithm, only X25519.
https://briansmith.org/rustdoc/ring/agreement/fn.agree_ephemeral.html

Here is the key exchange algorithm for Ed25519.
https://github.com/DaGenix/rust-crypto/blob/master/src/ed25519.rs#L132-L151

But I need to adopt for key generation of substrate.

ref: https://crypto.stackexchange.com/questions/27866/why-curve25519-for-encryption-but-ed25519-for-signatures

Implement CLI

like

init: // each account has 100 unit at the time of initialization
 	- address0: 0xaa
 	- spending_key0: 0x4ab
 	- address1: 0xab
 	- spending_key1: 0x1c8
 	・・・
 transfer 0xab<receiver> 10<amount> 0x4ab<spending_key>
 	- success
 balance 0xaa<addr> 0x4ab<spending_key>
 	- 90
 all_balances
 	- 0xaa => 0xdaf
 	- 0xab => 0xfa3
 	・・・

Inside the transfer would be

transfer(sender, receiver, amount, sk) {
 	r,v = api::get_balance(sender) // GET
 	proof = prove() // embedded params
 	enc = encrypt()
 	tx = gen_tx()
 	runtime_api::execute_block() // POST
 }

For getting the balances, needed decryption.

 get_balance(addr) -> r, v {
 	enc = get_storage(addr, from_index)
 	p = dec(enc)
 	calc(p)
 }

Fix something wrong with the pairing test for a swap of the endian

{
let mut rdecoded_le = R::default();
let mut rdecoded_be_flip = R::default();
let mut v: Vec<u8> = vec![];
r.write_le(&mut &mut v).unwrap();
// This reads in little-endian, so we are done.
rdecoded_le.read_le(&mut &v[..]).unwrap();
// This reads in big-endian, so we perform a swap of the
// bytes beforehand.
let v: Vec<u8> = v.into_iter().rev().collect();
rdecoded_be_flip.read_be(&mut &v[..]).unwrap();
assert_eq!(rdecoded_le, rdecoded_be_flip);
}

got the following error.

thread 'bls12_381::fq::fq_repr_tests' panicked at 'assertion failed: `(left == right)`
  left: `FqRepr([5457830654796382876, 14052294085650741142, 9037930377914938456, 17127803672399921366, 8651480755814397574, 10649476550251866400])`,
 right: `FqRepr([10649476550251866400, 8651480755814397574, 17127803672399921366, 9037930377914938456, 14052294085650741142, 5457830654796382876])`', pairing/src/tests/repr.rs:53:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
test bls12_381::fq::fq_repr_tests ... FAILED

[Part 1] Define parameters of confidential transfers and inputs of zk proof

parameters of confidential transfers

  • commitment root (anchor)
    A treestate consists of a note commitment tree and a nullifier set. The nullifier set is always updated together with the note commitment tree.
    The input treestate of each subsequent transaction in a block is the output treestate of the immediately preceding transaction.
    Namely, an anchor is the output treestate of either a previous block, or a previous JoinSplit transfer in this transaction

  • nullifier
    nullifier for the input note.

  • Note commitment:
    note commitment for the output note.

  • public key
    a key agreement public key, used to derive the key for encryption of the transmitted notes ciphertext.

  • random
    a seed that must be chosen independently at random for each transactions.

  • tag
    a tag that bind h_sig to each private key of the input notes
    where h_sig = hash(random, nullifier, pubkey)
    In order to avoid malleability.

  • zk proof
    a zero knowledge proof

  • encrypted Note
    ciphertext components for the encrypted output note.

inputs of zk proof

primary input (public)

  • commitment root
  • nullifier
  • Note commitment
  • h_sig
  • tag

auxiliary inputs (private)

  • merkle path
  • position
  • Note_old
  • Note_new
  • private key
  • phi (for uniquness of rho)
  • merkle path enforcement

Use travis CI with wasm files in gitignore

wasm files are included here.

// code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(),
code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/zero_chain_runtime_wasm.wasm").to_vec(),

// include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm")
include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/zero_chain_runtime_wasm.wasm")

Refs:

For wasm, add to zero-chain-proofs

bellman = { git = "https://github.com/osuketh/bellman", branch = "wasm" }
pairing = { git = "https://github.com/sorpaas/pairing", default-features = false }

Ensure if `reader` is consumed in no_std

reader.read(g1_repr.as_mut())?;
let a = g1_repr
.into_affine()
.map_err(|_| io::Error::InvalidData)
.and_then(|e| if e.is_zero() {
Err(io::Error::PointInfinity)
} else {
Ok(e)
})?;
reader.read(g2_repr.as_mut())?;
let b = g2_repr
.into_affine()
.map_err(|_| io::Error::InvalidData)
.and_then(|e| if e.is_zero() {
Err(io::Error::PointInfinity)
} else {
Ok(e)
})?;
reader.read(g1_repr.as_mut())?;
let c = g1_repr
.into_affine()
.map_err(|_| io::Error::InvalidData)
.and_then(|e| if e.is_zero() {
Err(io::Error::PointInfinity)
} else {
Ok(e)
})?;

Each of read function should consume the reader data.

Fix the test of zk_proof byte-cast.

The test fails because the dummy_engine is not implemented the from_affine() for the test.

error logs

---- proof::tests::test_proof_into_from stdout ----
thread 'proof::tests::test_proof_into_from' panicked at 'not yet implemented', bellman-verifier/src/tests/dummy_engine.rs:400:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

fn test_proof_into_from() {
// let mut rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
// let proof1 = bellman_verifier::Proof::<DummyEngine> {
// a: Fr(Wrapping(3269)),
// b: Fr(Wrapping(471)),
// c: Fr(Wrapping(8383)),
// };
// let proof_b = Proof::test_from_proof(&proof1);
// println!("proof_b: {:?}", proof_b);
// let proof2 = proof_b.test_into_proof().unwrap();
// assert!(proof1 == proof2);

Make correct sig hash for the compatibility with substrate

Need to be compatible with the signed data field between signing and verifying.

In unchecked_mortal_compact_extrinsic, the signature verification is implemented here.
https://github.com/paritytech/substrate/blob/1997487ec082f436e4c3279402d4528d67c861be/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs#L85-L96

In oo7, the signing scheme is implemented here.
https://github.com/paritytech/oo7/blob/79856e56658ad2b71115af5f682ac5d71a4f9ab3/packages/oo7-substrate/src/transact.js#L27-L42

Ensure if the public attributes are safe in pairing

Ensure if it is needed to change public to public(crate).

pub x: $basefield,
pub y: $basefield,
pub infinity: bool

pub struct Fq(pub FqRepr);

But if these are changed, the test of bellman-verifier would be failed because the proof is hard-coded, it cannot access as these fields are private out of the pairing crate.

let proof = Proof::<Bls12> {
a: G1Affine {
x: Fq(FqRepr([16739797345307447054, 8770073581945912782, 2136235734558249053, 15708693206467346864, 8490922573673252286, 1579948179538746271])),
y: Fq(FqRepr([6020268861830312380, 12879642226817054130, 17904268384441769431, 15221266273771162992, 5384025118770475327, 1217424206270675696])),
infinity: false
},
b: G2Affine {
x: Fq2 {
c0: Fq(FqRepr([1955900693533848923, 1207270260807916624, 10030599496790334806, 13310839817113796132, 7335494448760471336, 1520001478562200471])),
c1: Fq(FqRepr([10867545881237734656, 11292327308906943064, 4286427264655280722, 5033346395315998832, 9316987264960049565, 1093242448245841130]))
},
y: Fq2 {
c0: Fq(FqRepr([6242954237310667968, 4585560269108097072, 5517602464819718440, 11574556308726901230, 9576729709326690239, 433440758793164942])),
c1: Fq(FqRepr([11180820212476238720, 13504112200989036594, 2176986271111729977, 4481942420924131750, 16599268505710547724, 922146901424495142]))
},
infinity: false
},
c: G1Affine {
x: Fq(FqRepr([16362720867114782945, 14827736289902972547, 7987695302896742039, 14289613131851611182, 7162884718192410854, 605698044002088945])),
y: Fq(FqRepr([3093450141616622888, 7767002491037351418, 5972324121568597438, 2377138492074911281, 701452421528324862, 1373508511228186748])),
infinity: false
}
};

Protect front running attacks

Add the pending transfer.
In the confidential transfer function, add epoch_check, roll over pendings and update last_epoch.

pub fn confTransfer() {
  RollOver(sender_addr)
  RollOver(recipient_addr)
  ・・・
  balances[sender_addr] += Enc(-value)
  pending_transfer[recipient_addr] += Enc(value)
  ・・・
}

fn RollOver(addr) {
  let H = block.number
  let e = H/E
  if lastRollOver[addr] < e:
    Set balance[addr] += pending_transfer[addr]
    Set pending_transfer[addr] = (1, 1)
    Set lastRollOver[addr] = e
}

In the storage, Add pending_transfer_map and last_epoch_map

storage{
  pending_transfer: map address => pending_value
  last_epoch: map address => block_height
  ・・・
}

Add attributes for structs

In order to send the own defined struct to substrate, needed to add attributes of Encode, Decode, Default.

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.