diff --git a/.gitignore b/.gitignore index 9998471e3..654dc48a9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,12 +5,15 @@ /target/* /proof/*.bin -/zkas -/drk -/darkfid /cashierd +/dao-cli +/daod +/darkfid +/dnetview +/drk /gatewayd /ircd -/map +/tau-cli +/taud /vanityaddr -/dnetview +/zkas diff --git a/Cargo.toml b/Cargo.toml index 16a2260ff..7962d3aed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -251,20 +251,3 @@ required-features = ["node"] name = "dao-process" path = "example/dao_process.rs" required-features = ["crypto", "zkas"] - -# ZK VM Proof examples - -[[example]] -name = "arithmetic" -path = "proof/arithmetic.rs" -required-features = ["crypto", "zkas"] - -[[example]] -name = "mint" -path = "proof/mint.rs" -required-features = ["crypto", "zkas"] - -[[example]] -name = "burn" -path = "proof/burn.rs" -required-features = ["crypto", "zkas"] diff --git a/Makefile b/Makefile index 6595f2abc..bf3bab922 100644 --- a/Makefile +++ b/Makefile @@ -33,22 +33,18 @@ fix: clippy: $(CARGO) clippy --release --all-features --all -test: test-vm test-tx - $(CARGO) test --release --all-features --all - -test-tx: - $(CARGO) run --release --features=node,zkas --example tx - +# zkas source files which we want to compile for tests VM_SRC = proof/arithmetic.zk proof/mint.zk proof/burn.zk VM_BIN = $(VM_SRC:=.bin) $(VM_BIN): zkas $(VM_SRC) ./zkas $(basename $@) -o $@ -test-vm: $(VM_BIN) - $(CARGO) run --release --features=crypto,zkas --example arithmetic - $(CARGO) run --release --features=crypto,zkas --example mint - $(CARGO) run --release --features=crypto,zkas --example burn +test: $(VM_BIN) test-tx + $(CARGO) test --release --all-features --all + +test-tx: + $(CARGO) run --release --features=node,zkas --example tx clean: rm -f $(BINS) @@ -63,4 +59,4 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/$$i; \ done; -.PHONY: all check fix clippy test test-tx test-vm clean install uninstall +.PHONY: all check fix clippy test test-tx clean install uninstall diff --git a/proof/dao.rs b/proof/dao.rs deleted file mode 100644 index 238e2a476..000000000 --- a/proof/dao.rs +++ /dev/null @@ -1,161 +0,0 @@ -use halo2_gadgets::primitives::{ - poseidon, - poseidon::{ConstantLength, P128Pow5T3}, -}; -use halo2_proofs::dev::MockProver; -use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree}; -use pasta_curves::{ - arithmetic::CurveAffine, - group::{ - ff::{Field, PrimeField}, - Curve, Group, - }, - pallas, -}; -use rand::rngs::OsRng; -use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed}; - -use darkfi::{ - crypto::{ - keypair::Keypair, - merkle_node::MerkleNode, - schnorr::SchnorrSecret, - util::{mod_r_p, pedersen_commitment_scalar}, - }, - zk::vm::{Witness, ZkCircuit}, - zkas::decoder::ZkBinary, - Result, -}; - -fn main() -> Result<()> { - let loglevel = match option_env!("RUST_LOG") { - Some("debug") => LevelFilter::Debug, - Some("trace") => LevelFilter::Trace, - Some(_) | None => LevelFilter::Info, - }; - TermLogger::init(loglevel, Config::default(), Mixed, Auto)?; - - let bincode = include_bytes!("dao.zk.bin"); - let zkbin = ZkBinary::decode(bincode)?; - - // ============= - // Initial state - // ============= - let authority = Keypair::random(&mut OsRng); - - let spend_contract = pallas::Base::random(&mut OsRng); - let cur_balance = pallas::Base::from(666); - let old_serial = pallas::Base::random(&mut OsRng); - let old_bulla_blind = pallas::Base::random(&mut OsRng); - - let message = [spend_contract, cur_balance, old_serial, old_bulla_blind]; - let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init(); - let our_dao = hasher.hash(message); - - // Merkle tree of DAOs - let mut tree = BridgeTree::::new(100); - let dao0 = pallas::Base::random(&mut OsRng); - let dao2 = pallas::Base::random(&mut OsRng); - - tree.append(&MerkleNode(dao0)); - tree.witness(); - - tree.append(&MerkleNode(our_dao)); - tree.witness(); - - tree.append(&MerkleNode(dao2)); - tree.witness(); - - // ======== - // Proposal - // ======== - let amount_to_send = pallas::Base::from(42); - let proposal_destination = pallas::Point::random(&mut OsRng); - let proposal_coords = proposal_destination.to_affine().coordinates().unwrap(); - let proposal_blind = pallas::Base::random(&mut OsRng); - - let message = [amount_to_send, *proposal_coords.x(), *proposal_coords.y(), proposal_blind]; - let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init(); - let proposal = hasher.hash(message); - - // Sign the proposal by the authority - let _signature = authority.secret.sign(&proposal.to_repr()); - - // ============== - // Voting process - // ============== - // The voting process happens now, and when finished, the votes are revealed. - // Votes are weighted by balance. - - let vote0 = pallas::Base::from(44); - let vote0_blind = pallas::Scalar::random(&mut OsRng); - - let vote1 = pallas::Base::from(13); - let vote1_blind = pallas::Scalar::random(&mut OsRng); - - let vote2 = -pallas::Base::from(49); // This is a NO vote - let vote2_blind = pallas::Scalar::random(&mut OsRng); - - let votes = vote0 + vote1 + vote2; - let vote_blinds = vote0_blind + vote1_blind + vote2_blind; - - if votes < pallas::Base::from(1) { - // The voting process result is negative, so we don't do anything. - return Ok(()) - } - - // ================== - // Proof construction - // ================== - let (leaf_pos, merkle_path) = tree.authentication_path(&MerkleNode(our_dao)).unwrap(); - let leaf_pos: u64 = leaf_pos.into(); - let leaf_pos = leaf_pos as u32; - - let new_serial = pallas::Base::random(&mut OsRng); - let new_bulla_blind = pallas::Base::random(&mut OsRng); - - let new_balance = cur_balance - amount_to_send; - - let message = [spend_contract, new_balance, new_serial, new_bulla_blind]; - let hasher = poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init(); - let new_bulla = hasher.hash(message); - - let merkle_root = tree.root(); - - let value_blind = pallas::Scalar::random(&mut OsRng); - let value_commit = pedersen_commitment_scalar(mod_r_p(amount_to_send), value_blind); - let value_coords = value_commit.to_affine().coordinates().unwrap(); - - let public_inputs = vec![ - spend_contract, - old_serial, - merkle_root.0, - proposal, - *value_coords.x(), - *value_coords.y(), - new_bulla, - ]; - - let prover_witnesses = vec![ - Witness::Base(Some(spend_contract)), - Witness::Base(Some(cur_balance)), - Witness::Base(Some(old_serial)), - Witness::Base(Some(old_bulla_blind)), - Witness::Uint32(Some(leaf_pos)), - Witness::MerklePath(Some(merkle_path.try_into().unwrap())), - Witness::Base(Some(amount_to_send)), - Witness::Base(Some(*proposal_coords.x())), - Witness::Base(Some(*proposal_coords.y())), - Witness::Base(Some(proposal_blind)), - Witness::Scalar(Some(value_blind)), - Witness::Base(Some(new_serial)), - Witness::Base(Some(new_bulla_blind)), - ]; - - let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone()); - - let prover = MockProver::::run(11, &circuit, vec![public_inputs])?; - assert_eq!(prover.verify(), Ok(())); - - Ok(()) -} diff --git a/proof/dao.zk b/proof/dao.zk deleted file mode 100644 index d81b0e7ab..000000000 --- a/proof/dao.zk +++ /dev/null @@ -1,68 +0,0 @@ -constant "DAO" { - EcFixedPointShort VALUE_COMMIT_VALUE, - EcFixedPoint VALUE_COMMIT_RANDOM, -} - -contract "DAO" { - Base spend_contract, - Base cur_balance, - Base old_serial, - Base old_bulla_blind, - - Uint32 leaf_pos, - MerklePath merkle_path, - - Base amount_to_send, - Base pub_x, - Base pub_y, - Base proposal_blind, - Scalar proposal_value_blind, - - Base new_serial, - Base new_bulla_blind, -} - -circuit "DAO" { - # Enforce spend contract - constrain_instance(spend_contract); - - # Reveal serial number - constrain_instance(old_serial); - - # Poseidon hash of the current treasury - bulla = poseidon_hash( - spend_contract, - cur_balance, - old_serial, - old_bulla_blind, - ); - - # Enforce the merkle root - D = calculate_merkle_root(leaf_pos, merkle_path, bulla); - constrain_instance(D); - - # Poseidon hash of the proposal (output 0) - proposal = poseidon_hash(amount_to_send, pub_x, pub_y, proposal_blind); - constrain_instance(proposal); - - # Pedersen commitment to the amount we're sending - valc_v = ec_mul_short(amount_to_send, VALUE_COMMIT_VALUE); - valc_r = ec_mul(proposal_value_blind, VALUE_COMMIT_RANDOM); - value_commit = ec_add(valc_v, valc_r); - value_commit_x = ec_get_x(value_commit); - value_commit_y = ec_get_y(value_commit); - constrain_instance(value_commit_x); - constrain_instance(value_commit_y); - - # Calculate remaining balance in treasury - new_balance = base_sub(cur_balance, amount_to_send); - - # Poseidon hash of the new treasury - new_bulla = poseidon_hash( - spend_contract, - new_balance, - new_serial, - new_bulla_blind, - ); - constrain_instance(new_bulla); -} diff --git a/src/crypto/token_list.rs b/src/crypto/token_list.rs index 56cdf68de..1046f4252 100644 --- a/src/crypto/token_list.rs +++ b/src/crypto/token_list.rs @@ -185,7 +185,7 @@ mod tests { use super::*; fn _get_sol_tokens() -> Result { - let file_contents = include_bytes!("../../testdata/solanatokenlisttest.json"); + let file_contents = include_bytes!("../../tests/data/solanatokenlisttest.json"); let sol_tokenlist: Value = serde_json::from_slice(file_contents)?; let tokens = sol_tokenlist["tokens"].as_array().ok_or(Error::TokenParseError)?.clone(); @@ -195,7 +195,7 @@ mod tests { } fn _get_eth_tokens() -> Result { - let file_contents = include_bytes!("../../testdata/erc20tokenlisttest.json"); + let file_contents = include_bytes!("../../tests/data/erc20tokenlisttest.json"); let eth_tokenlist: Value = serde_json::from_slice(file_contents)?; let tokens = eth_tokenlist["tokens"].as_array().ok_or(Error::TokenParseError)?.clone(); diff --git a/proof/arithmetic.rs b/tests/arithmetic_proof.rs similarity index 67% rename from proof/arithmetic.rs rename to tests/arithmetic_proof.rs index 759c742c1..de792d076 100644 --- a/proof/arithmetic.rs +++ b/tests/arithmetic_proof.rs @@ -7,21 +7,13 @@ use darkfi::{ zkas::decoder::ZkBinary, Result, }; -use log::info; use pasta_curves::pallas; use rand::rngs::OsRng; -use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed}; - -fn main() -> Result<()> { - let loglevel = match option_env!("RUST_LOG") { - Some("debug") => LevelFilter::Debug, - Some("trace") => LevelFilter::Trace, - Some(_) | None => LevelFilter::Info, - }; - TermLogger::init(loglevel, Config::default(), Mixed, Auto)?; +#[test] +fn arithmetic_proof() -> Result<()> { /* ANCHOR: main */ - let bincode = include_bytes!("arithmetic.zk.bin"); + let bincode = include_bytes!("../proof/arithmetic.zk.bin"); let zkbin = ZkBinary::decode(bincode)?; // ====== @@ -44,7 +36,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone()); - info!(target: "PROVER", "Building proving key and creating the zero-knowledge proof"); let proving_key = ProvingKey::build(11, &circuit); let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?; @@ -58,7 +49,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(verifier_witnesses, zkbin); - info!(target: "VERIFIER", "Building verifying key and verifying the zero-knowledge proof"); let verifying_key = VerifyingKey::build(11, &circuit); proof.verify(&verifying_key, &public_inputs)?; /* ANCHOR_END: main */ diff --git a/proof/burn.rs b/tests/burn_proof.rs similarity index 87% rename from proof/burn.rs rename to tests/burn_proof.rs index 7093f1e1f..db0fa4e2a 100644 --- a/proof/burn.rs +++ b/tests/burn_proof.rs @@ -15,25 +15,17 @@ use halo2_gadgets::primitives::{ poseidon::{ConstantLength, P128Pow5T3}, }; use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree}; -use log::info; use pasta_curves::{ arithmetic::CurveAffine, group::{ff::Field, Curve}, pallas, }; use rand::rngs::OsRng; -use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed}; - -fn main() -> Result<()> { - let loglevel = match option_env!("RUST_LOG") { - Some("debug") => LevelFilter::Debug, - Some("trace") => LevelFilter::Trace, - Some(_) | None => LevelFilter::Info, - }; - TermLogger::init(loglevel, Config::default(), Mixed, Auto)?; +#[test] +fn burn_proof() -> Result<()> { /* ANCHOR: main */ - let bincode = include_bytes!("burn.zk.bin"); + let bincode = include_bytes!("../proof/burn.zk.bin"); let zkbin = ZkBinary::decode(bincode)?; // ====== @@ -121,7 +113,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone()); - info!(target: "PROVER", "Building proving key and creating the zero-knowledge proof"); let proving_key = ProvingKey::build(11, &circuit); let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?; @@ -146,7 +137,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(verifier_witnesses, zkbin); - info!(target: "VERIFIER", "Building verifying key and verifying the zero-knowledge proof"); let verifying_key = VerifyingKey::build(11, &circuit); proof.verify(&verifying_key, &public_inputs)?; /* ANCHOR_END: main */ diff --git a/testdata/erc20tokenlisttest.json b/tests/data/erc20tokenlisttest.json similarity index 100% rename from testdata/erc20tokenlisttest.json rename to tests/data/erc20tokenlisttest.json diff --git a/testdata/solanatokenlisttest.json b/tests/data/solanatokenlisttest.json similarity index 100% rename from testdata/solanatokenlisttest.json rename to tests/data/solanatokenlisttest.json diff --git a/proof/mint.rs b/tests/mint_proof.rs similarity index 82% rename from proof/mint.rs rename to tests/mint_proof.rs index 7db33d912..f4d4d6a4f 100644 --- a/proof/mint.rs +++ b/tests/mint_proof.rs @@ -13,25 +13,17 @@ use halo2_gadgets::primitives::{ poseidon, poseidon::{ConstantLength, P128Pow5T3}, }; -use log::info; use pasta_curves::{ arithmetic::CurveAffine, group::{ff::Field, Curve}, pallas, }; use rand::rngs::OsRng; -use simplelog::{ColorChoice::Auto, Config, LevelFilter, TermLogger, TerminalMode::Mixed}; - -fn main() -> Result<()> { - let loglevel = match option_env!("RUST_LOG") { - Some("debug") => LevelFilter::Debug, - Some("trace") => LevelFilter::Trace, - Some(_) | None => LevelFilter::Info, - }; - TermLogger::init(loglevel, Config::default(), Mixed, Auto)?; +#[test] +fn mint_proof() -> Result<()> { /* ANCHOR: main */ - let bincode = include_bytes!("mint.zk.bin"); + let bincode = include_bytes!("../proof/mint.zk.bin"); let zkbin = ZkBinary::decode(bincode)?; // ====== @@ -75,7 +67,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone()); - info!(target: "PROVER", "Building proving key and creating the zero-knowledge proof"); let proving_key = ProvingKey::build(11, &circuit); let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?; @@ -98,7 +89,6 @@ fn main() -> Result<()> { // Create the circuit let circuit = ZkCircuit::new(verifier_witnesses, zkbin); - info!(target: "VERIFIER", "Building verifying key and verifying the zero-knowledge proof"); let verifying_key = VerifyingKey::build(11, &circuit); proof.verify(&verifying_key, &public_inputs)?; /* ANCHOR_END: main */