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 Issues

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:

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

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 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
  ・・・
}

[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

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)
 }

Add attributes for structs

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

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

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

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.

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.