From 8171d529d11700f2c95ff53f8f26b6666ff24533 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Mon, 9 Jun 2025 16:30:12 +0530 Subject: [PATCH 01/10] feat: add 0.5 to merkle tree --- merkle-tree-example/Cargo.toml | 23 ++++++------- merkle-tree-example/src/common.rs | 16 +++++---- merkle-tree-example/src/constraints.rs | 28 ++++++++-------- merkle-tree-example/src/lib.rs | 46 +++++++++++++++++++++----- 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/merkle-tree-example/Cargo.toml b/merkle-tree-example/Cargo.toml index 45c772a..8075780 100644 --- a/merkle-tree-example/Cargo.toml +++ b/merkle-tree-example/Cargo.toml @@ -1,22 +1,21 @@ [package] name = "merkle-tree-example" -version = "0.3.0" +version = "0.5.0" authors = ["arkworks contributors"] edition = "2018" [dependencies] -ark-ff = { version = "^0.3.0", default-features = false } -ark-ec = { version = "^0.3.0", default-features = false } -ark-ed-on-bls12-381 = { version = "^0.3.0", features = ["r1cs"] } -ark-bls12-381 = { version = "^0.3.0", default-features = false } -ark-std = { version = "^0.3.0", default-features = false } -ark-relations = { version = "^0.3.0", default-features = false } +ark-ff = { version = "^0.5.0", default-features = false } +ark-ec = { version = "^0.5.0", default-features = false } +ark-ed-on-bls12-381 = { version = "^0.5.0", features = ["r1cs"] } +ark-bls12-381 = { version = "^0.5.0", default-features = false } +ark-std = { version = "^0.5.0", default-features = false } +ark-relations = { version = "^0.5.0", default-features = false } -ark-r1cs-std = { version = "^0.3.0", default-features = false } -ark-snark = { version = "^0.3.0", default-features = false } +ark-r1cs-std = { version = "^0.5.0", default-features = false } +ark-snark = { version = "^0.5.0", default-features = false } -ark-serialize = { version = "^0.3.0", default-features = false } - -ark-crypto-primitives = { version = "^0.3.0", default-features = true, features = [ "r1cs" ] } +ark-serialize = { version = "^0.5.0", default-features = false } +ark-crypto-primitives = { version = "^0.5.0", default-features = true, features = [ "r1cs" , "crh", "merkle_tree"] } tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } tracing-subscriber = { version = "0.2" } diff --git a/merkle-tree-example/src/common.rs b/merkle-tree-example/src/common.rs index 9e7c978..5278e75 100644 --- a/merkle-tree-example/src/common.rs +++ b/merkle-tree-example/src/common.rs @@ -1,14 +1,16 @@ -use ark_crypto_primitives::crh::constraints::{CRHGadget, TwoToOneCRHGadget}; use ark_crypto_primitives::crh::injective_map::constraints::{ - PedersenCRHCompressorGadget, TECompressorGadget, + PedersenCRHCompressorGadget, PedersenTwoToOneCRHCompressorGadget, TECompressorGadget, }; +use ark_crypto_primitives::crh::injective_map::PedersenTwoToOneCRHCompressor; use ark_crypto_primitives::crh::{ injective_map::{PedersenCRHCompressor, TECompressor}, pedersen, }; +use ark_crypto_primitives::crh::{CRHSchemeGadget, TwoToOneCRHSchemeGadget}; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; -pub type TwoToOneHash = PedersenCRHCompressor; +pub type TwoToOneHash = + PedersenTwoToOneCRHCompressor; #[derive(Clone, PartialEq, Eq, Hash)] pub struct TwoToOneWindow; @@ -19,7 +21,6 @@ impl pedersen::Window for TwoToOneWindow { } pub type LeafHash = PedersenCRHCompressor; - #[derive(Clone, PartialEq, Eq, Hash)] pub struct LeafWindow; @@ -29,7 +30,7 @@ impl pedersen::Window for LeafWindow { const NUM_WINDOWS: usize = 144; } -pub type TwoToOneHashGadget = PedersenCRHCompressorGadget< +pub type TwoToOneHashGadget = PedersenTwoToOneCRHCompressorGadget< EdwardsProjective, TECompressor, TwoToOneWindow, @@ -45,8 +46,9 @@ pub type LeafHashGadget = PedersenCRHCompressorGadget< TECompressorGadget, >; -pub type LeafHashParamsVar = >::ParametersVar; +pub type LeafHashParamsVar = + >::ParametersVar; pub type TwoToOneHashParamsVar = - >::ParametersVar; + >::ParametersVar; pub type ConstraintF = ark_ed_on_bls12_381::Fq; diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index d81e2b1..5dac115 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -1,6 +1,6 @@ -use crate::common::*; +use crate::{common::*, MerkleConfig, MerkleConfigVar}; use crate::{Root, SimplePath}; -use ark_crypto_primitives::crh::{TwoToOneCRH, TwoToOneCRHGadget, CRH}; +use ark_crypto_primitives::crh::{CRHScheme, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; use ark_crypto_primitives::merkle_tree::constraints::PathVar; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; @@ -9,18 +9,18 @@ use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisE // just know that these are types that you can use.) /// The R1CS equivalent of the the Merkle tree root. -pub type RootVar = >::OutputVar; +pub type RootVar = + >::OutputVar; /// The R1CS equivalent of the the Merkle tree path. -pub type SimplePathVar = - PathVar; +pub type SimplePathVar = PathVar; //////////////////////////////////////////////////////////////////////////////// pub struct MerkleTreeVerification { // These are constants that will be embedded into the circuit - pub leaf_crh_params: ::Parameters, - pub two_to_one_crh_params: ::Parameters, + pub leaf_crh_params: ::Parameters, + pub two_to_one_crh_params: ::Parameters, // These are the public inputs to the circuit. pub root: Root, @@ -75,15 +75,15 @@ fn merkle_tree_constraints_correctness() { let mut rng = ark_std::test_rng(); // First, let's sample the public parameters for the hash functions: - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_crh_params = ::setup(&mut rng).unwrap(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_crh_params = ::setup(&mut rng).unwrap(); // Next, let's construct our tree. // This follows the API in https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/mod.rs#L156 let tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[1u8, 2u8, 3u8, 10u8, 9u8, 17u8, 70u8, 45u8], // the i-th entry is the i-th leaf. + &[&[1u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. ) .unwrap(); @@ -136,15 +136,15 @@ fn merkle_tree_constraints_soundness() { let mut rng = ark_std::test_rng(); // First, let's sample the public parameters for the hash functions: - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_crh_params = ::setup(&mut rng).unwrap(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_crh_params = ::setup(&mut rng).unwrap(); // Next, let's construct our tree. // This follows the API in https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/mod.rs#L156 let tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[1u8, 2u8, 3u8, 10u8, 9u8, 17u8, 70u8, 45u8], // the i-th entry is the i-th leaf. + &[&[1u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. ) .unwrap(); @@ -152,7 +152,7 @@ fn merkle_tree_constraints_soundness() { let second_tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[4u8, 2u8, 3u8, 10u8, 9u8, 17u8, 70u8, 45u8], // the i-th entry is the i-th leaf. + &[&[4u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. ) .unwrap(); diff --git a/merkle-tree-example/src/lib.rs b/merkle-tree-example/src/lib.rs index f9f5341..3427636 100644 --- a/merkle-tree-example/src/lib.rs +++ b/merkle-tree-example/src/lib.rs @@ -1,7 +1,11 @@ -use ark_crypto_primitives::crh::TwoToOneCRH; -use ark_crypto_primitives::merkle_tree::{Config, MerkleTree, Path}; +use ark_crypto_primitives::crh::{ + CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, +}; +use ark_crypto_primitives::merkle_tree::constraints::{BytesVarDigestConverter, ConfigGadget}; +use ark_crypto_primitives::merkle_tree::{ByteDigestConverter, Config, MerkleTree, Path}; pub mod common; +use ark_r1cs_std::uint8::UInt8; use common::*; mod constraints; @@ -12,35 +16,61 @@ pub struct MerkleConfig; impl Config for MerkleConfig { // Our Merkle tree relies on two hashes: one to hash leaves, and one to hash pairs // of internal nodes. + type Leaf = [u8]; type LeafHash = LeafHash; type TwoToOneHash = TwoToOneHash; + type LeafDigest = ::Output; + type LeafInnerDigestConverter = ByteDigestConverter; + type InnerDigest = ::Output; } +struct MerkleConfigVar; +impl ConfigGadget for MerkleConfigVar { + type Leaf = LeafVar; + type LeafDigest = >::OutputVar; + type LeafInnerConverter = BytesVarDigestConverter; + type InnerDigest = + >::OutputVar; + type LeafHash = LeafHashGadget; + type TwoToOneHash = TwoToOneHashGadget; +} + +type LeafVar = [UInt8]; + /// A Merkle tree containing account information. pub type SimpleMerkleTree = MerkleTree; /// The root of the account Merkle tree. -pub type Root = ::Output; +pub type Root = ::Output; /// A membership proof for a given account. pub type SimplePath = Path; // Run this test via `cargo test --release test_merkle_tree`. #[test] fn test_merkle_tree() { - use ark_crypto_primitives::crh::CRH; + use ark_crypto_primitives::crh::CRHScheme; // Let's set up an RNG for use within tests. Note that this is *not* safe // for any production use. let mut rng = ark_std::test_rng(); // First, let's sample the public parameters for the hash functions: - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_crh_params = ::setup(&mut rng).unwrap(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_crh_params = ::setup(&mut rng).unwrap(); // Next, let's construct our tree. // This follows the API in https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/mod.rs#L156 let tree = SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[1u8, 2u8, 3u8, 10u8, 9u8, 17u8, 70u8, 45u8], // the i-th entry is the i-th leaf. + &[ + &[1u8][..], + &[2u8][..], + &[3u8][..], + &[10u8][..], + &[9u8][..], + &[17u8][..], + &[70u8][..], + &[45u8][..], + ], // the i-th entry is the i-th leaf. ) .unwrap(); @@ -56,7 +86,7 @@ fn test_merkle_tree() { &leaf_crh_params, &two_to_one_crh_params, &root, - &[9u8], // The claimed leaf + &[9u8][..], // The claimed leaf ) .unwrap(); assert!(result); From 0624e63615fb577c26d40f171ecc00f88ac740dc Mon Sep 17 00:00:00 2001 From: rac-sri Date: Mon, 9 Jun 2025 16:38:53 +0530 Subject: [PATCH 02/10] feat: add 0.5 to merkle tree solutions --- merkle-tree-example/src/constraints.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index 5dac115..3f7fcf2 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -56,9 +56,14 @@ impl ConstraintSynthesizer for MerkleTreeVerification { // Hint: look at https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/constraints.rs#L135 // TODO: FILL IN THE BLANK! - // let is_member = XYZ - // - // is_member.enforce_equal(&Boolean::TRUE)?; + let is_member = path.verify_membership( + &leaf_crh_params, + &two_to_one_crh_params, + &root, + &leaf_bytes.as_slice(), + )?; + + is_member.enforce_equal(&Boolean::TRUE)?; Ok(()) } From 27a6fb30360bc2a04944abd5abbfd74aeac2e1c4 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Mon, 9 Jun 2025 16:45:01 +0530 Subject: [PATCH 03/10] feat: fix 0.5 tests --- merkle-tree-example/src/constraints.rs | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index 3f7fcf2..4f6c180 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -88,7 +88,16 @@ fn merkle_tree_constraints_correctness() { let tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[&[1u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. + &[ + &[1u8][..], + &[2u8][..], + &[3u8][..], + &[10u8][..], + &[9u8][..], + &[17u8][..], + &[70u8][..], + &[45u8][..], + ], // the i-th entry is the i-th leaf. ) .unwrap(); @@ -149,7 +158,16 @@ fn merkle_tree_constraints_soundness() { let tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[&[1u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. + &[ + &[1u8][..], + &[2u8][..], + &[3u8][..], + &[10u8][..], + &[9u8][..], + &[17u8][..], + &[70u8][..], + &[45u8][..], + ], // the i-th entry is the i-th leaf. ) .unwrap(); @@ -157,7 +175,16 @@ fn merkle_tree_constraints_soundness() { let second_tree = crate::SimpleMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, - &[&[4u8][..], &[2u8][..], &[3u8][..], &[10u8][..], &[9u8][..]], // the i-th entry is the i-th leaf. + &[ + &[4u8][..], + &[2u8][..], + &[3u8][..], + &[10u8][..], + &[9u8][..], + &[17u8][..], + &[70u8][..], + &[45u8][..], + ], // the i-th entry is the i-th leaf. ) .unwrap(); From 49ee54423eac6a23d8a1cb020f195101ec6b2e88 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Mon, 9 Jun 2025 16:45:55 +0530 Subject: [PATCH 04/10] feat: cleanup --- merkle-tree-example/src/constraints.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index 4f6c180..dacb741 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -56,14 +56,8 @@ impl ConstraintSynthesizer for MerkleTreeVerification { // Hint: look at https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/constraints.rs#L135 // TODO: FILL IN THE BLANK! - let is_member = path.verify_membership( - &leaf_crh_params, - &two_to_one_crh_params, - &root, - &leaf_bytes.as_slice(), - )?; - - is_member.enforce_equal(&Boolean::TRUE)?; + // let is_member = XYZ; + // is_member.enforce_equal(&Boolean::TRUE)?; Ok(()) } From 527be1d1e4d9aaa62de5d90311228ad5f08d378a Mon Sep 17 00:00:00 2001 From: rac-sri Date: Fri, 13 Jun 2025 15:46:02 +0530 Subject: [PATCH 05/10] feat: payment and rollup upgrade --- rollup/Cargo.toml | 26 +++---- rollup/src/account.rs | 9 +-- rollup/src/ledger.rs | 46 ++++++------ rollup/src/rollup.rs | 11 +-- simple-payments/Cargo.toml | 25 ++++--- simple-payments/src/account.rs | 9 ++- simple-payments/src/ledger.rs | 57 +++++++++++++-- .../src/random_oracle/blake2s/constraints.rs | 2 +- simple-payments/src/random_oracle/mod.rs | 3 +- simple-payments/src/signature/constraints.rs | 5 +- simple-payments/src/signature/mod.rs | 5 +- .../src/signature/schnorr/constraints.rs | 52 +++++++------ simple-payments/src/signature/schnorr/mod.rs | 73 +++++++++++-------- simple-payments/src/transaction.rs | 2 +- 14 files changed, 196 insertions(+), 129 deletions(-) diff --git a/rollup/Cargo.toml b/rollup/Cargo.toml index 159c831..ac767fd 100644 --- a/rollup/Cargo.toml +++ b/rollup/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ark-rollup" -version = "0.3.0" +version = "0.5.0" authors = [ "arkworks contributors" ] description = "A SNARK-based rollup for a simple payments system" repository = "https://github.com/arkworks-rs/r1cs-tutorial" @@ -11,21 +11,21 @@ license = "MIT/Apache-2.0" edition = "2018" [dependencies] -ark-ff = { version = "^0.3.0", default-features = false } -ark-ec = { version = "^0.3.0", default-features = false } -ark-ed-on-bls12-381 = { version = "^0.3.0", features = ["r1cs"] } -ark-bls12-381 = { version = "^0.3.0" } -ark-std = { version = "^0.3.0", default-features = false } -ark-relations = { version = "^0.3.0", default-features = false, optional = true } +ark-ff = { version = "^0.5.0", default-features = false } +ark-ec = { version = "^0.5.0", default-features = false } +ark-ed-on-bls12-381 = { version = "^0.5.0", features = ["r1cs"] } +ark-bls12-381 = { version = "^0.5.0" } +ark-std = { version = "^0.5.0", default-features = false } +ark-relations = { version = "^0.5.0", default-features = false, optional = true } -ark-r1cs-std = { version = "^0.3.0", optional = true, default-features = false } -ark-snark = { version = "^0.3.0", default-features = false } -ark-groth16 = { version = "^0.3.0" } -ark-gm17 = { version = "^0.3.0" } +ark-r1cs-std = { version = "^0.5.0", optional = true, default-features = false } +ark-snark = { version = "^0.5.0", default-features = false } +ark-groth16 = { version = "^0.5.0" } -ark-serialize = { version = "^0.3.0", default-features = false } -ark-crypto-primitives = { version = "^0.3.0", default-features = true } +ark-serialize = { version = "^0.5.0", default-features = false } + +ark-crypto-primitives = { version = "^0.5.0", default-features = true } ark-simple-payments = { path = "../simple-payments", default-features = true } blake2 = { version = "0.9" } digest = "0.9" diff --git a/rollup/src/account.rs b/rollup/src/account.rs index 3c4d996..c48e3b5 100644 --- a/rollup/src/account.rs +++ b/rollup/src/account.rs @@ -1,8 +1,8 @@ use crate::ledger::*; use crate::ConstraintF; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; -use ark_r1cs_std::bits::{uint8::UInt8, ToBytesGadget}; use ark_r1cs_std::prelude::*; +use ark_r1cs_std::uint8::UInt8; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_simple_payments::account::*; use ark_simple_payments::signature::schnorr::constraints::*; @@ -47,12 +47,7 @@ impl AccountInformationVar { /// Convert the account information to bytes. #[tracing::instrument(target = "r1cs", skip(self))] pub fn to_bytes_le(&self) -> Vec> { - self.public_key - .to_bytes() - .unwrap() - .into_iter() - .chain(self.balance.to_bytes_le()) - .collect() + self.public_key.to_bytes_le().unwrap() } } diff --git a/rollup/src/ledger.rs b/rollup/src/ledger.rs index abcb5bb..e69b6ec 100644 --- a/rollup/src/ledger.rs +++ b/rollup/src/ledger.rs @@ -1,14 +1,12 @@ use crate::ConstraintF; use ark_crypto_primitives::crh::injective_map::constraints::{ - PedersenCRHCompressorGadget, TECompressorGadget, -}; -use ark_crypto_primitives::crh::{ - constraints::{CRHGadget, TwoToOneCRHGadget}, - injective_map::TECompressor, + PedersenCRHCompressorGadget, PedersenTwoToOneCRHCompressorGadget, TECompressorGadget, }; + +use ark_crypto_primitives::crh::{injective_map::TECompressor, CRHScheme, TwoToOneCRHScheme}; +use ark_crypto_primitives::crh::{CRHSchemeGadget, TwoToOneCRHSchemeGadget}; use ark_crypto_primitives::merkle_tree::constraints::PathVar; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; -use ark_r1cs_std::bits::uint64::UInt64; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_simple_payments::ledger::*; @@ -22,7 +20,7 @@ pub struct AmountVar(pub UInt64); impl AmountVar { #[tracing::instrument(target = "r1cs", skip(self))] pub fn to_bytes_le(&self) -> Vec> { - self.0.to_bytes().unwrap() + self.0.to_bytes_le().unwrap() } #[tracing::instrument(target = "r1cs", skip(self, other))] @@ -33,17 +31,17 @@ impl AmountVar { // converting the field elements to bits // and then checking if the 65th bit is 0. // TODO: Demonstrate via circuit profiling if this needs optimization. - let self_bits = self.0.to_bits_le(); - let self_fe = Boolean::le_bits_to_fp_var(&self_bits)?; - let other_bits = other.0.to_bits_le(); - let other_fe = Boolean::le_bits_to_fp_var(&other_bits)?; + let self_bits = self.0.to_bits_le().unwrap(); + let self_fe = Boolean::le_bits_to_fp(&self_bits)?; + let other_bits = other.0.to_bits_le().unwrap(); + let other_fe = Boolean::le_bits_to_fp(&other_bits)?; let res_fe = self_fe + other_fe; - let res_bz = res_fe.to_bytes()?; + let res_bz = res_fe.to_bytes_le()?; // Ensure 65th bit is 0 // implies 8th word (0-indexed) is 0 res_bz[8].enforce_equal(&UInt8::::constant(0))?; // Add sum - let result = UInt64::addmany(&[self.0.clone(), other.0.clone()])?; + let result = UInt64::wrapping_add_many(&[self.0.clone(), other.0.clone()])?; Ok(AmountVar(result)) } @@ -54,12 +52,12 @@ impl AmountVar { // We then cast the field element to bits, and ensure the top bits are 0. // We then convert these bits to a field element // TODO: Demonstrate via circuit profiling if this needs optimization. - let self_bits = self.0.to_bits_le(); - let self_fe = Boolean::le_bits_to_fp_var(&self_bits)?; - let other_bits = other.0.to_bits_le(); - let other_fe = Boolean::le_bits_to_fp_var(&other_bits)?; + let self_bits = self.0.to_bits_le().unwrap(); + let self_fe = Boolean::le_bits_to_fp(&self_bits)?; + let other_bits = other.0.to_bits_le().unwrap(); + let other_fe = Boolean::le_bits_to_fp(&other_bits)?; let res_fe = self_fe - other_fe; - let res_bz = res_fe.to_bytes()?; + let res_bz = res_fe.to_bytes_le()?; // Ensure top bit is 0 res_bz[res_bz.len() - 1].enforce_equal(&UInt8::::constant(0))?; // Convert to UInt64 @@ -79,7 +77,7 @@ impl AllocVar for AmountVar { } } -pub type TwoToOneHashGadget = PedersenCRHCompressorGadget< +pub type TwoToOneHashGadget = PedersenTwoToOneCRHCompressorGadget< EdwardsProjective, TECompressor, TwoToOneWindow, @@ -96,11 +94,13 @@ pub type LeafHashGadget = PedersenCRHCompressorGadget< >; pub type AccRootVar = - >::OutputVar; -pub type AccPathVar = PathVar; -pub type LeafHashParamsVar = >::ParametersVar; + >::OutputVar; + +pub type AccPathVar = PathVar; +pub type LeafHashParamsVar = + >::ParametersVar; pub type TwoToOneHashParamsVar = - >::ParametersVar; + >::ParametersVar; /// The parameters that are used in transaction creation and validation. pub struct ParametersVar { diff --git a/rollup/src/rollup.rs b/rollup/src/rollup.rs index 3cd5c82..eee852c 100644 --- a/rollup/src/rollup.rs +++ b/rollup/src/rollup.rs @@ -265,6 +265,7 @@ mod test { use ark_simple_payments::account::AccountId; use ark_simple_payments::ledger::{Amount, Parameters, State}; use ark_simple_payments::transaction::Transaction; + use ark_std::rand::SeedableRng; use tracing_subscriber::layer::SubscriberExt; fn test_cs(rollup: Rollup) -> bool { @@ -456,7 +457,7 @@ mod test { // Use a circuit just to generate the circuit let circuit_defining_cs = build_two_tx_circuit(); - let mut rng = ark_std::test_rng(); + let mut rng = ark_std::rand::rngs::StdRng::from_seed([1; 32]); let (pk, vk) = Groth16::::circuit_specific_setup(circuit_defining_cs, &mut rng).unwrap(); @@ -468,8 +469,8 @@ mod test { circuit_to_verify_against.final_root.unwrap(), ]; - let proof = Groth16::prove(&pk, circuit_to_verify_against, &mut rng).unwrap(); - let valid_proof = Groth16::verify(&vk, &public_input, &proof).unwrap(); + let proof = Groth16::::prove(&pk, circuit_to_verify_against, &mut rng).unwrap(); + let valid_proof = Groth16::::verify(&vk, &public_input, &proof).unwrap(); assert!(valid_proof); // Use the same circuit but with different inputs to verify against @@ -481,8 +482,8 @@ mod test { circuit_to_verify_against.final_root.unwrap(), ]; - let proof = Groth16::prove(&pk, circuit_to_verify_against, &mut rng).unwrap(); - let valid_proof = Groth16::verify(&vk, &public_input, &proof).unwrap(); + let proof = Groth16::::prove(&pk, circuit_to_verify_against, &mut rng).unwrap(); + let valid_proof = Groth16::::verify(&vk, &public_input, &proof).unwrap(); assert!(!valid_proof); } } diff --git a/simple-payments/Cargo.toml b/simple-payments/Cargo.toml index 1a9dd99..636d372 100644 --- a/simple-payments/Cargo.toml +++ b/simple-payments/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ark-simple-payments" -version = "0.3.0" +version = "0.5.0" authors = [ "arkworks contributors" ] description = "A simple payments system" repository = "https://github.com/arkworks-rs/r1cs-tutorial" @@ -10,20 +10,23 @@ include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" edition = "2018" +[toolchain] +channel = "nightly" + [dependencies] -ark-ff = { version = "^0.3.0", default-features = false } -ark-ec = { version = "^0.3.0", default-features = false } -ark-ed-on-bls12-381 = { version = "^0.3.0", features = ["r1cs"] } -ark-bls12-381 = { version = "^0.3.0", default-features = false } -ark-std = { version = "^0.3.0", default-features = false } -ark-relations = { version = "^0.3.0", default-features = false, optional = true } +ark-ff = { version = "^0.5.0", default-features = false } +ark-ec = { version = "^0.5.0", default-features = false } +ark-ed-on-bls12-381 = { version = "^0.5.0", features = ["r1cs"] } +ark-bls12-381 = { version = "^0.5.0", default-features = false } +ark-std = { version = "^0.5.0", default-features = false } +ark-relations = { version = "^0.5.0", default-features = false, optional = true } -ark-r1cs-std = { version = "^0.3.0", optional = true, default-features = false } -ark-snark = { version = "^0.3.0", default-features = false } +ark-r1cs-std = { version = "^0.5.0", optional = true, default-features = false } +ark-snark = { version = "^0.5.0", default-features = false } -ark-serialize = { version = "^0.3.0", default-features = false } +ark-serialize = { version = "^0.5.0", default-features = false } -ark-crypto-primitives = { version = "^0.3.0", default-features = true } +ark-crypto-primitives = { version = "^0.5.0", default-features = true, features=["prf", "crh", "merkle_tree"] } blake2 = { version = "0.9" } digest = "0.9" derivative = { version = "2.0", features = ["use_core"] } diff --git a/simple-payments/src/account.rs b/simple-payments/src/account.rs index 1d95dee..ddec198 100644 --- a/simple-payments/src/account.rs +++ b/simple-payments/src/account.rs @@ -1,6 +1,7 @@ use crate::ledger::*; use crate::signature::schnorr; use ark_ed_on_bls12_381::EdwardsProjective; +use ark_serialize::CanonicalSerialize; /// Account public key used to verify transaction signatures. pub type AccountPublicKey = schnorr::PublicKey; @@ -37,6 +38,12 @@ pub struct AccountInformation { impl AccountInformation { /// Convert the account information to bytes. pub fn to_bytes_le(&self) -> Vec { - ark_ff::to_bytes![self.public_key, self.balance.to_bytes_le()].unwrap() + let mut public_key_bytes = Vec::new(); + self.public_key + .serialize_compressed(&mut public_key_bytes) + .unwrap(); + + public_key_bytes.extend_from_slice(&self.balance.to_bytes_le()); + public_key_bytes } } diff --git a/simple-payments/src/ledger.rs b/simple-payments/src/ledger.rs index 7ce590e..f0e2c36 100644 --- a/simple-payments/src/ledger.rs +++ b/simple-payments/src/ledger.rs @@ -1,12 +1,20 @@ use crate::account::{AccountId, AccountInformation, AccountPublicKey, AccountSecretKey}; use crate::signature::{schnorr, SignatureScheme}; use crate::transaction::Transaction; +use ark_crypto_primitives::crh::injective_map::constraints::{ + PedersenCRHCompressorGadget, PedersenTwoToOneCRHCompressorGadget, TECompressorGadget, +}; +use ark_crypto_primitives::crh::injective_map::PedersenTwoToOneCRHCompressor; use ark_crypto_primitives::crh::{ injective_map::{PedersenCRHCompressor, TECompressor}, - pedersen, TwoToOneCRH, CRH, + pedersen, CRHScheme, TwoToOneCRHScheme, }; -use ark_crypto_primitives::merkle_tree::{self, MerkleTree, Path}; +use ark_crypto_primitives::crh::{CRHSchemeGadget, TwoToOneCRHSchemeGadget}; +use ark_crypto_primitives::merkle_tree::constraints::{BytesVarDigestConverter, ConfigGadget}; +use ark_crypto_primitives::merkle_tree::{self, ByteDigestConverter, MerkleTree, Path}; +use ark_ed_on_bls12_381::constraints::EdwardsVar; use ark_ed_on_bls12_381::EdwardsProjective; +use ark_r1cs_std::uint8::UInt8; use ark_std::rand::Rng; use std::collections::HashMap; @@ -32,15 +40,15 @@ impl Amount { #[derive(Clone)] pub struct Parameters { pub sig_params: schnorr::Parameters, - pub leaf_crh_params: ::Parameters, - pub two_to_one_crh_params: ::Parameters, + pub leaf_crh_params: ::Parameters, + pub two_to_one_crh_params: ::Parameters, } impl Parameters { pub fn sample(rng: &mut R) -> Self { let sig_params = schnorr::Schnorr::setup(rng).unwrap(); - let leaf_crh_params = ::setup(rng).unwrap(); - let two_to_one_crh_params = ::setup(rng).unwrap(); + let leaf_crh_params = ::setup(rng).unwrap(); + let two_to_one_crh_params = ::setup(rng).unwrap(); Self { sig_params, leaf_crh_params, @@ -49,7 +57,16 @@ impl Parameters { } } -pub type TwoToOneHash = PedersenCRHCompressor; +pub type TwoToOneHash = + PedersenTwoToOneCRHCompressor; + +pub type TwoToOneHashGadget = PedersenTwoToOneCRHCompressorGadget< + EdwardsProjective, + TECompressor, + TwoToOneWindow, + EdwardsVar, + TECompressorGadget, +>; #[derive(Clone, PartialEq, Eq, Hash)] pub struct TwoToOneWindow; @@ -61,6 +78,13 @@ impl pedersen::Window for TwoToOneWindow { } pub type LeafHash = PedersenCRHCompressor; +pub type LeafHashGadget = PedersenCRHCompressorGadget< + EdwardsProjective, + TECompressor, + LeafWindow, + EdwardsVar, + TECompressorGadget, +>; #[derive(Clone, PartialEq, Eq, Hash)] pub struct LeafWindow; @@ -71,17 +95,34 @@ impl pedersen::Window for LeafWindow { const NUM_WINDOWS: usize = 4; } +pub type ConstraintF = ark_ed_on_bls12_381::Fq; +type LeafVar = [UInt8]; #[derive(Clone)] pub struct MerkleConfig; impl merkle_tree::Config for MerkleConfig { + type Leaf = [u8]; type LeafHash = LeafHash; type TwoToOneHash = TwoToOneHash; + type LeafDigest = ::Output; + type LeafInnerDigestConverter = ByteDigestConverter; + type InnerDigest = ::Output; +} + +pub struct MerkleConfigVar; +impl ConfigGadget for MerkleConfigVar { + type Leaf = LeafVar; + type LeafDigest = >::OutputVar; + type LeafInnerConverter = BytesVarDigestConverter; + type InnerDigest = + >::OutputVar; + type LeafHash = LeafHashGadget; + type TwoToOneHash = TwoToOneHashGadget; } /// A Merkle tree containing account information. pub type AccMerkleTree = MerkleTree; /// The root of the account Merkle tree. -pub type AccRoot = ::Output; +pub type AccRoot = ::Output; /// A membership proof for a given account. pub type AccPath = Path; diff --git a/simple-payments/src/random_oracle/blake2s/constraints.rs b/simple-payments/src/random_oracle/blake2s/constraints.rs index 6e9a198..ff32188 100644 --- a/simple-payments/src/random_oracle/blake2s/constraints.rs +++ b/simple-payments/src/random_oracle/blake2s/constraints.rs @@ -27,7 +27,7 @@ impl RandomOracleGadget for ROGadget { } let mut result = Vec::new(); for int in evaluate_blake2s(&input_bits)?.into_iter() { - let chunk = int.to_bytes()?; + let chunk = int.to_bytes_le().unwrap(); result.extend_from_slice(&chunk); } Ok(OutputVar(result)) diff --git a/simple-payments/src/random_oracle/mod.rs b/simple-payments/src/random_oracle/mod.rs index 200ac2e..dea53fa 100644 --- a/simple-payments/src/random_oracle/mod.rs +++ b/simple-payments/src/random_oracle/mod.rs @@ -1,4 +1,3 @@ -use ark_ff::bytes::ToBytes; use ark_std::hash::Hash; use ark_std::rand::Rng; @@ -13,7 +12,7 @@ pub use constraints::*; /// Interface to a RandomOracle pub trait RandomOracle { - type Output: ToBytes + Clone + Eq + core::fmt::Debug + Hash + Default; + type Output: Clone + Eq + core::fmt::Debug + Hash + Default; type Parameters: Clone + Default; fn setup(r: &mut R) -> Result; diff --git a/simple-payments/src/signature/constraints.rs b/simple-payments/src/signature/constraints.rs index 5fc6f36..200c2dc 100644 --- a/simple-payments/src/signature/constraints.rs +++ b/simple-payments/src/signature/constraints.rs @@ -38,7 +38,8 @@ pub trait SigRandomizePkGadget { #[cfg(test)] mod test { use crate::signature::{schnorr, schnorr::constraints::*, *}; - use ark_ec::ProjectiveCurve; + + use ark_ec::CurveGroup; use ark_ed_on_bls12_381::constraints::EdwardsVar as JubJubVar; use ark_ed_on_bls12_381::EdwardsProjective as JubJub; use ark_ff::PrimeField; @@ -80,7 +81,7 @@ mod test { #[test] fn schnorr_signature_test() { - type F = ::BaseField; + type F = ::BaseField; let message = "Hi, I am a Schnorr signature!"; sign_and_verify::< F, diff --git a/simple-payments/src/signature/mod.rs b/simple-payments/src/signature/mod.rs index f380713..07be106 100644 --- a/simple-payments/src/signature/mod.rs +++ b/simple-payments/src/signature/mod.rs @@ -1,5 +1,4 @@ use ark_crypto_primitives::Error; -use ark_ff::bytes::ToBytes; use ark_std::hash::Hash; use ark_std::rand::Rng; @@ -12,8 +11,8 @@ pub mod schnorr; pub trait SignatureScheme { type Parameters: Clone + Send + Sync; - type PublicKey: ToBytes + Hash + Eq + Clone + Default + Send + Sync; - type SecretKey: ToBytes + Clone + Default; + type PublicKey: Hash + Eq + Clone + Default + Send + Sync; + type SecretKey: Clone + Default; type Signature: Clone + Default + Send + Sync; fn setup(rng: &mut R) -> Result; diff --git a/simple-payments/src/signature/schnorr/constraints.rs b/simple-payments/src/signature/schnorr/constraints.rs index b8ee4cc..f36a783 100644 --- a/simple-payments/src/signature/schnorr/constraints.rs +++ b/simple-payments/src/signature/schnorr/constraints.rs @@ -1,8 +1,9 @@ -use ark_ec::ProjectiveCurve; -use ark_ff::{to_bytes, Field}; -use ark_r1cs_std::{bits::uint8::UInt8, prelude::*}; +use ark_ec::CurveGroup; +use ark_ff::Field; +use ark_r1cs_std::prelude::*; use ark_relations::r1cs::ConstraintSystemRef; use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_serialize::CanonicalSerialize; use ark_std::vec::Vec; use crate::random_oracle::blake2s::constraints::{ParametersVar as B2SParamsVar, ROGadget}; @@ -15,10 +16,10 @@ use core::{borrow::Borrow, marker::PhantomData}; use crate::signature::schnorr::{Parameters, PublicKey, Schnorr, Signature}; -type ConstraintF = <::BaseField as Field>::BasePrimeField; +type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Clone)] -pub struct ParametersVar>> +pub struct ParametersVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -29,10 +30,10 @@ where #[derive(Derivative)] #[derivative( - Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), - Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") + Debug(bound = "C: CurveGroup, GC: CurveVar>"), + Clone(bound = "C: CurveGroup, GC: CurveVar>") )] -pub struct PublicKeyVar>> +pub struct PublicKeyVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -43,10 +44,10 @@ where #[derive(Derivative)] #[derivative( - Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), - Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") + Debug(bound = "C: CurveGroup, GC: CurveVar>"), + Clone(bound = "C: CurveGroup, GC: CurveVar>") )] -pub struct SignatureVar>> +pub struct SignatureVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -56,7 +57,7 @@ where _group: PhantomData, } -pub struct SchnorrSignatureVerifyGadget>> +pub struct SchnorrSignatureVerifyGadget>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -68,7 +69,7 @@ where impl SigVerifyGadget, ConstraintF> for SchnorrSignatureVerifyGadget where - C: ProjectiveCurve, + C: CurveGroup, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -96,8 +97,8 @@ where if parameters.salt.is_some() { hash_input.extend_from_slice(parameters.salt.as_ref().unwrap()); } - hash_input.extend_from_slice(&public_key.pub_key.to_bytes()?); - hash_input.extend_from_slice(&claimed_prover_commitment.to_bytes()?); + hash_input.extend_from_slice(public_key.pub_key.to_bytes_le().unwrap().as_slice()); + hash_input.extend_from_slice(claimed_prover_commitment.to_bytes_le().unwrap().as_slice()); hash_input.extend_from_slice(message); let b2s_params = >>::new_constant( @@ -112,7 +113,7 @@ where impl AllocVar, ConstraintF> for ParametersVar where - C: ProjectiveCurve, + C: CurveGroup, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -152,7 +153,7 @@ where impl AllocVar, ConstraintF> for PublicKeyVar where - C: ProjectiveCurve, + C: CurveGroup, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -171,7 +172,8 @@ where impl AllocVar, ConstraintF> for SignatureVar where - C: ProjectiveCurve, + C: CurveGroup, + C::ScalarField: CanonicalSerialize, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -182,7 +184,11 @@ where ) -> Result { f().and_then(|val| { let cs = cs.into(); - let response_bytes = to_bytes![val.borrow().prover_response].unwrap(); + let mut response_bytes = Vec::new(); + val.borrow() + .prover_response + .serialize_compressed(&mut response_bytes) + .unwrap(); let challenge_bytes = val.borrow().verifier_challenge; let mut prover_response = Vec::>>::new(); let mut verifier_challenge = Vec::>>::new(); @@ -211,7 +217,7 @@ where impl EqGadget> for PublicKeyVar where - C: ProjectiveCurve, + C: CurveGroup, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -243,11 +249,11 @@ where impl ToBytesGadget> for PublicKeyVar where - C: ProjectiveCurve, + C: CurveGroup, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { - fn to_bytes(&self) -> Result>>, SynthesisError> { - self.pub_key.to_bytes() + fn to_bytes_le(&self) -> Result>>, SynthesisError> { + self.pub_key.to_bytes_le() } } diff --git a/simple-payments/src/signature/schnorr/mod.rs b/simple-payments/src/signature/schnorr/mod.rs index c6ccbe1..472e9a6 100644 --- a/simple-payments/src/signature/schnorr/mod.rs +++ b/simple-payments/src/signature/schnorr/mod.rs @@ -1,12 +1,11 @@ use super::SignatureScheme; use ark_crypto_primitives::Error; -use ark_ec::{AffineCurve, ProjectiveCurve}; +use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{ - bytes::ToBytes, fields::{Field, PrimeField}, - to_bytes, ToConstraintField, UniformRand, + ToConstraintField, UniformRand, }; -use ark_std::io::{Result as IoResult, Write}; +use ark_serialize::CanonicalSerialize; use ark_std::rand::Rng; use ark_std::{hash::Hash, marker::PhantomData, vec::Vec}; use blake2::Blake2s; @@ -16,39 +15,32 @@ use derivative::Derivative; #[cfg(feature = "r1cs")] pub mod constraints; -pub struct Schnorr { +pub struct Schnorr { _group: PhantomData, } #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve"), Debug)] -pub struct Parameters { +#[derivative(Clone(bound = "C: CurveGroup"), Debug)] +pub struct Parameters { pub generator: C::Affine, pub salt: Option<[u8; 32]>, } -pub type PublicKey = ::Affine; +pub type PublicKey = ::Affine; #[derive(Clone, Default, Debug)] -pub struct SecretKey { +pub struct SecretKey { pub secret_key: C::ScalarField, pub public_key: PublicKey, } -impl ToBytes for SecretKey { - #[inline] - fn write(&self, writer: W) -> IoResult<()> { - self.secret_key.write(writer) - } -} - #[derive(Clone, Default, Debug)] -pub struct Signature { +pub struct Signature { pub prover_response: C::ScalarField, pub verifier_challenge: [u8; 32], } -impl SignatureScheme for Schnorr +impl SignatureScheme for Schnorr where C::ScalarField: PrimeField, { @@ -61,7 +53,7 @@ where // let setup_time = start_timer!(|| "SchnorrSig::Setup"); let salt = None; - let generator = C::prime_subgroup_generator().into(); + let generator = C::generator().into(); // end_timer!(setup_time); Ok(Parameters { generator, salt }) @@ -76,7 +68,10 @@ where // Secret is a random scalar x // the pubkey is y = xG let secret_key = C::ScalarField::rand(rng); - let public_key = parameters.generator.mul(secret_key).into(); + let public_key = parameters + .generator + .mul_bigint(secret_key.into_bigint()) + .into(); // end_timer!(keygen_time); Ok(( @@ -101,7 +96,10 @@ where let random_scalar: C::ScalarField = C::ScalarField::rand(rng); // Commit to the random scalar via r := k ยท G. // This is the prover's first msg in the Sigma protocol. - let prover_commitment = parameters.generator.mul(random_scalar).into_affine(); + let prover_commitment = parameters + .generator + .mul_bigint(random_scalar.into_bigint()) + .into_affine(); // Hash everything to get verifier challenge. // e := H(salt || pubkey || r || msg); @@ -109,8 +107,14 @@ where if parameters.salt != None { hash_input.extend_from_slice(¶meters.salt.unwrap()); } - hash_input.extend_from_slice(&to_bytes![sk.public_key]?); - hash_input.extend_from_slice(&to_bytes![prover_commitment]?); + let mut pk_bytes = Vec::new(); + sk.public_key.serialize_compressed(&mut pk_bytes).unwrap(); + hash_input.extend_from_slice(&pk_bytes); + let mut prover_commitment_bytes = Vec::new(); + prover_commitment + .serialize_compressed(&mut prover_commitment_bytes) + .unwrap(); + hash_input.extend_from_slice(&prover_commitment_bytes); hash_input.extend_from_slice(message); let hash_digest = Blake2s::digest(&hash_input); @@ -150,8 +154,11 @@ where // sG = kG - eY // kG = sG + eY // so we first solve for kG. - let mut claimed_prover_commitment = parameters.generator.mul(*prover_response); - let public_key_times_verifier_challenge = pk.mul(verifier_challenge_fe); + let mut claimed_prover_commitment = parameters + .generator + .mul_bigint(prover_response.into_bigint()); + let public_key_times_verifier_challenge = + pk.mul_bigint(verifier_challenge_fe.into_bigint()); claimed_prover_commitment += &public_key_times_verifier_challenge; let claimed_prover_commitment = claimed_prover_commitment.into_affine(); @@ -160,8 +167,14 @@ where if parameters.salt != None { hash_input.extend_from_slice(¶meters.salt.unwrap()); } - hash_input.extend_from_slice(&to_bytes![pk]?); - hash_input.extend_from_slice(&to_bytes![claimed_prover_commitment]?); + let mut pk_bytes = Vec::new(); + pk.serialize_compressed(&mut pk_bytes).unwrap(); + hash_input.extend_from_slice(&pk_bytes); + let mut prover_commitment_bytes = Vec::new(); + claimed_prover_commitment + .serialize_compressed(&mut prover_commitment_bytes) + .unwrap(); + hash_input.extend_from_slice(&prover_commitment_bytes); hash_input.extend_from_slice(message); // cast the hash output to get e @@ -184,11 +197,13 @@ pub fn bytes_to_bits(bytes: &[u8]) -> Vec { bits } -impl> +impl> ToConstraintField for Parameters +where + C::Affine: ToConstraintField, { #[inline] fn to_field_elements(&self) -> Option> { - self.generator.into_projective().to_field_elements() + self.generator.to_field_elements() } } diff --git a/simple-payments/src/transaction.rs b/simple-payments/src/transaction.rs index 0a7afc8..94a9f5f 100644 --- a/simple-payments/src/transaction.rs +++ b/simple-payments/src/transaction.rs @@ -57,7 +57,7 @@ impl Transaction { ¶meters.leaf_crh_params, ¶meters.two_to_one_crh_params, &state.account_merkle_tree.root(), - &sender_acc_info.to_bytes_le(), + sender_acc_info.to_bytes_le(), ) .unwrap() }; From 14a7fb80347c378240ecf75145fe7e84d400f245 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Wed, 9 Jul 2025 17:51:48 +0530 Subject: [PATCH 06/10] feat: fixed merkle tree --- merkle-tree-example/src/constraints.rs | 10 +++- rollup/src/rollup.rs | 40 +++++++++------- rollup/src/transaction.rs | 47 ++++++++++++++----- simple-payments/src/signature/constraints.rs | 1 + .../src/signature/schnorr/constraints.rs | 2 + 5 files changed, 68 insertions(+), 32 deletions(-) diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index dacb741..4f6c180 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -56,8 +56,14 @@ impl ConstraintSynthesizer for MerkleTreeVerification { // Hint: look at https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/constraints.rs#L135 // TODO: FILL IN THE BLANK! - // let is_member = XYZ; - // is_member.enforce_equal(&Boolean::TRUE)?; + let is_member = path.verify_membership( + &leaf_crh_params, + &two_to_one_crh_params, + &root, + &leaf_bytes.as_slice(), + )?; + + is_member.enforce_equal(&Boolean::TRUE)?; Ok(()) } diff --git a/rollup/src/rollup.rs b/rollup/src/rollup.rs index eee852c..9eb64e6 100644 --- a/rollup/src/rollup.rs +++ b/rollup/src/rollup.rs @@ -199,7 +199,10 @@ impl ConstraintSynthesizer for Rollup })?; // ... and authentication path after the update. // TODO: Fill in the following - // let sender_post_path = ??? + let sender_post_path = + AccPathVar::new_witness(ark_relations::ns!(cs, "Sender Post-Path"), || { + sender_post_path.ok_or(SynthesisError::AssignmentMissing) + })?; // Declare the recipient's initial account balance... let recipient_acc_info = AccountInformationVar::new_witness( @@ -214,7 +217,10 @@ impl ConstraintSynthesizer for Rollup // ... and authentication path after the update. // TODO: Fill in the following - // let recipient_post_path = ??? + let recipient_post_path = + AccPathVar::new_witness(ark_relations::ns!(cs, "Recipient Post-Path"), || { + recipient_post_path.ok_or(SynthesisError::AssignmentMissing) + })?; // Declare the state root before the transaction... let pre_tx_root = @@ -229,29 +235,29 @@ impl ConstraintSynthesizer for Rollup // Enforce that the state root after the previous transaction equals // the starting state root for this transaction - // TODO: Write this + prev_root.enforce_equal(&pre_tx_root)?; // Validate that the transaction signature and amount is correct. // TODO: Uncomment this - // tx.validate( - // &ledger_params, - // &sender_acc_info, - // &sender_pre_path, - // &sender_post_path, - // &recipient_acc_info, - // &recipient_pre_path, - // &recipient_post_path, - // &pre_tx_root, - // &post_tx_root, - // )? - // .enforce_equal(&Boolean::TRUE)?; + tx.validate( + &ledger_params, + &sender_acc_info, + &sender_pre_path, + &sender_post_path, + &recipient_acc_info, + &recipient_pre_path, + &recipient_post_path, + &pre_tx_root, + &post_tx_root, + )? + .enforce_equal(&Boolean::TRUE)?; // Set the root for the next transaction. prev_root = post_tx_root; } // Check that the final root is consistent with the root computed after // applying all state transitions - // TODO: implement this + prev_root.enforce_equal(&final_root)?; Ok(()) } } @@ -425,7 +431,7 @@ mod test { .update_balance(alice_id, Amount(1000)) .expect("Alice's account should exist"); // Let's make an account for Bob. - let (bob_id, _bob_pk, bob_sk) = state.sample_keys_and_register(&pp, &mut rng).unwrap(); + let (bob_id, _bob_pk, _bob_sk) = state.sample_keys_and_register(&pp, &mut rng).unwrap(); let amount_to_send = rng.gen_range(0..200); diff --git a/rollup/src/transaction.rs b/rollup/src/transaction.rs index 6e124b3..e6593bf 100644 --- a/rollup/src/transaction.rs +++ b/rollup/src/transaction.rs @@ -79,41 +79,62 @@ impl TransactionVar { ) -> Result, SynthesisError> { // Verify the signature against the sender pubkey. // TODO: FILL IN THE BLANK - // let sig_verifies = ???; + let sig_verifies = + self.verify_signature(¶meters.sig_params, &pre_sender_acc_info.public_key)?; // Compute the new sender balance. let mut post_sender_acc_info = pre_sender_acc_info.clone(); // TODO: Safely subtract amount sent from the sender's balance - // post_sender_acc_info.balance = ???; + post_sender_acc_info.balance = post_sender_acc_info.balance.checked_sub(&self.amount)?; // TODO: Compute the new receiver balance, ensure its overflow safe. let mut post_recipient_acc_info = pre_recipient_acc_info.clone(); - // post_recipient_acc_info.balance = ??? + post_recipient_acc_info.balance = + post_recipient_acc_info.balance.checked_add(&self.amount)?; // Check that the pre-tx sender account information is correct with // respect to `pre_tx_root`, and that the post-tx sender account // information is correct with respect to `post_tx_root`. // HINT: Use the path structs // TODO: FILL IN THE FOLLOWING - // let sender_exists = ??? + let sender_exists = pre_sender_path.verify_membership( + ¶meters.leaf_crh_params, + ¶meters.two_to_one_crh_params, + &pre_root, + &pre_sender_acc_info.to_bytes_le().as_slice(), + )?; - // let sender_updated_correctly = ??? + let sender_updated_correctly = post_sender_path.verify_membership( + ¶meters.leaf_crh_params, + ¶meters.two_to_one_crh_params, + &post_root, + &post_sender_acc_info.to_bytes_le().as_slice(), + )?; // Check that the pre-tx recipient account information is correct with // respect to `pre_tx_root`, and that the post-tx recipient account // information is correct with respect to `post_tx_root`. // TODO: FILL IN THE FOLLOWING - // let recipient_exists = ??? + let recipient_exists = pre_recipient_path.verify_membership( + ¶meters.leaf_crh_params, + ¶meters.two_to_one_crh_params, + &pre_root, + &pre_recipient_acc_info.to_bytes_le().as_slice(), + )?; - // let recipient_updated_correctly = ??? + let recipient_updated_correctly = post_recipient_path.verify_membership( + ¶meters.leaf_crh_params, + ¶meters.two_to_one_crh_params, + &post_root, + &post_recipient_acc_info.to_bytes_le().as_slice(), + )?; // TODO: Uncomment the following - // sender_exists - // .and(&sender_updated_correctly)? - // .and(&recipient_exists)? - // .and(&recipient_updated_correctly)? - // .and(&sig_verifies) - Err(SynthesisError::Unsatisfiable) + sender_exists + .nand(&sender_updated_correctly)? + .nand(&recipient_exists)? + .nand(&recipient_updated_correctly)? + .nand(&sig_verifies) } } diff --git a/simple-payments/src/signature/constraints.rs b/simple-payments/src/signature/constraints.rs index 200c2dc..dcdb58c 100644 --- a/simple-payments/src/signature/constraints.rs +++ b/simple-payments/src/signature/constraints.rs @@ -68,6 +68,7 @@ mod test { let valid_sig_var = SG::verify(¶meters_var, &pk_var, &msg_var, &signature_var).unwrap(); valid_sig_var.enforce_equal(&Boolean::::TRUE).unwrap(); + assert!(cs.is_satisfied().unwrap()); } diff --git a/simple-payments/src/signature/schnorr/constraints.rs b/simple-payments/src/signature/schnorr/constraints.rs index f36a783..786cf64 100644 --- a/simple-payments/src/signature/schnorr/constraints.rs +++ b/simple-payments/src/signature/schnorr/constraints.rs @@ -85,9 +85,11 @@ where ) -> Result>, SynthesisError> { let prover_response = signature.prover_response.clone(); let verifier_challenge = signature.verifier_challenge.clone(); + let mut claimed_prover_commitment = parameters .generator .scalar_mul_le(prover_response.to_bits_le()?.iter())?; + let public_key_times_verifier_challenge = public_key .pub_key .scalar_mul_le(verifier_challenge.to_bits_le()?.iter())?; From 8346b55b69cc2da03690fb4a94b13e030ce6f807 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Fri, 11 Jul 2025 00:25:28 +0530 Subject: [PATCH 07/10] feat: fixed simple payment --- rollup/src/transaction.rs | 1 + simple-payments/Cargo.toml | 3 ++- simple-payments/src/signature/constraints.rs | 15 +++++++++++---- .../src/signature/schnorr/constraints.rs | 10 +++++----- simple-payments/src/signature/schnorr/mod.rs | 12 +++++++----- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/rollup/src/transaction.rs b/rollup/src/transaction.rs index e6593bf..52c80b6 100644 --- a/rollup/src/transaction.rs +++ b/rollup/src/transaction.rs @@ -371,6 +371,7 @@ mod test { let rollup = UnaryRollup::with_state_and_transaction(pp.clone(), bad_tx, &mut temp_state, false) .unwrap(); + assert!(!test_cs(rollup)); } } diff --git a/simple-payments/Cargo.toml b/simple-payments/Cargo.toml index 636d372..b5c1234 100644 --- a/simple-payments/Cargo.toml +++ b/simple-payments/Cargo.toml @@ -30,7 +30,8 @@ ark-crypto-primitives = { version = "^0.5.0", default-features = true, features= blake2 = { version = "0.9" } digest = "0.9" derivative = { version = "2.0", features = ["use_core"] } -tracing = { version = "0.1", default-features = false, features = [ "attributes" ], optional = true } +tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } +tracing-subscriber = { version = "0.2" } [features] default = [ "std", "parallel", "r1cs" ] diff --git a/simple-payments/src/signature/constraints.rs b/simple-payments/src/signature/constraints.rs index dcdb58c..2ccba36 100644 --- a/simple-payments/src/signature/constraints.rs +++ b/simple-payments/src/signature/constraints.rs @@ -1,8 +1,8 @@ +use crate::signature::SignatureScheme; use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; - -use crate::signature::SignatureScheme; +use tracing_subscriber::layer::SubscriberExt; pub trait SigVerifyGadget { type ParametersVar: AllocVar + Clone; @@ -44,8 +44,9 @@ mod test { use ark_ed_on_bls12_381::EdwardsProjective as JubJub; use ark_ff::PrimeField; use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; + use ark_relations::r1cs::{ConstraintLayer, ConstraintSystem, TracingMode}; use ark_std::test_rng; + use tracing_subscriber::layer::SubscriberExt; fn sign_and_verify>( message: &[u8], @@ -56,6 +57,11 @@ mod test { let sig = S::sign(¶meters, &sk, &message, rng).unwrap(); assert!(S::verify(¶meters, &pk, &message, &sig).unwrap()); + // let mut layer = ConstraintLayer::default(); + // layer.mode = TracingMode::All; + // let subscriber = tracing_subscriber::Registry::default().with(layer); + // let _guard = tracing::subscriber::set_default(subscriber); + let cs = ConstraintSystem::::new_ref(); let parameters_var = SG::ParametersVar::new_constant(cs.clone(), parameters).unwrap(); @@ -81,7 +87,7 @@ mod test { } #[test] - fn schnorr_signature_test() { + fn schnorr_signature_test_constraints() { type F = ::BaseField; let message = "Hi, I am a Schnorr signature!"; sign_and_verify::< @@ -89,6 +95,7 @@ mod test { schnorr::Schnorr, SchnorrSignatureVerifyGadget, >(message.as_bytes()); + failed_verification::>( message.as_bytes(), "Bad message".as_bytes(), diff --git a/simple-payments/src/signature/schnorr/constraints.rs b/simple-payments/src/signature/schnorr/constraints.rs index 786cf64..2daf4cd 100644 --- a/simple-payments/src/signature/schnorr/constraints.rs +++ b/simple-payments/src/signature/schnorr/constraints.rs @@ -99,14 +99,14 @@ where if parameters.salt.is_some() { hash_input.extend_from_slice(parameters.salt.as_ref().unwrap()); } - hash_input.extend_from_slice(public_key.pub_key.to_bytes_le().unwrap().as_slice()); + + let pub_key_bytes = public_key.pub_key.to_bytes_le().unwrap(); + + hash_input.extend_from_slice(pub_key_bytes.as_slice()); hash_input.extend_from_slice(claimed_prover_commitment.to_bytes_le().unwrap().as_slice()); hash_input.extend_from_slice(message); - let b2s_params = >>::new_constant( - ConstraintSystemRef::None, - (), - )?; + let b2s_params = B2SParamsVar; let obtained_verifier_challenge = ROGadget::evaluate(&b2s_params, &hash_input)?.0; obtained_verifier_challenge.is_eq(&verifier_challenge.to_vec()) diff --git a/simple-payments/src/signature/schnorr/mod.rs b/simple-payments/src/signature/schnorr/mod.rs index 472e9a6..9662a80 100644 --- a/simple-payments/src/signature/schnorr/mod.rs +++ b/simple-payments/src/signature/schnorr/mod.rs @@ -3,7 +3,7 @@ use ark_crypto_primitives::Error; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{ fields::{Field, PrimeField}, - ToConstraintField, UniformRand, + BigInteger, ToConstraintField, UniformRand, }; use ark_serialize::CanonicalSerialize; use ark_std::rand::Rng; @@ -107,12 +107,14 @@ where if parameters.salt != None { hash_input.extend_from_slice(¶meters.salt.unwrap()); } + let mut pk_bytes = Vec::new(); - sk.public_key.serialize_compressed(&mut pk_bytes).unwrap(); + sk.public_key.serialize_uncompressed(&mut pk_bytes).unwrap(); + hash_input.extend_from_slice(&pk_bytes); let mut prover_commitment_bytes = Vec::new(); prover_commitment - .serialize_compressed(&mut prover_commitment_bytes) + .serialize_uncompressed(&mut prover_commitment_bytes) .unwrap(); hash_input.extend_from_slice(&prover_commitment_bytes); hash_input.extend_from_slice(message); @@ -168,11 +170,11 @@ where hash_input.extend_from_slice(¶meters.salt.unwrap()); } let mut pk_bytes = Vec::new(); - pk.serialize_compressed(&mut pk_bytes).unwrap(); + pk.serialize_uncompressed(&mut pk_bytes).unwrap(); hash_input.extend_from_slice(&pk_bytes); let mut prover_commitment_bytes = Vec::new(); claimed_prover_commitment - .serialize_compressed(&mut prover_commitment_bytes) + .serialize_uncompressed(&mut prover_commitment_bytes) .unwrap(); hash_input.extend_from_slice(&prover_commitment_bytes); hash_input.extend_from_slice(message); From 855008335a7e4c2084289c6affe5e869b2666870 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Sun, 13 Jul 2025 00:16:40 +0530 Subject: [PATCH 08/10] feat: fixed all tests --- rollup/Cargo.toml | 1 + rollup/src/account.rs | 4 +++- rollup/src/ledger.rs | 20 ----------------- rollup/src/lib.rs | 2 +- rollup/src/transaction.rs | 22 ++++++++++--------- simple-payments/src/account.rs | 2 +- simple-payments/src/ledger.rs | 8 +++---- .../src/random_oracle/blake2s/constraints.rs | 2 +- simple-payments/src/signature/constraints.rs | 1 - .../src/signature/schnorr/constraints.rs | 3 +-- simple-payments/src/signature/schnorr/mod.rs | 2 +- simple-payments/src/transaction.rs | 1 + 12 files changed, 26 insertions(+), 42 deletions(-) diff --git a/rollup/Cargo.toml b/rollup/Cargo.toml index ac767fd..7710830 100644 --- a/rollup/Cargo.toml +++ b/rollup/Cargo.toml @@ -15,6 +15,7 @@ ark-ff = { version = "^0.5.0", default-features = false } ark-ec = { version = "^0.5.0", default-features = false } ark-ed-on-bls12-381 = { version = "^0.5.0", features = ["r1cs"] } ark-bls12-381 = { version = "^0.5.0" } + ark-std = { version = "^0.5.0", default-features = false } ark-relations = { version = "^0.5.0", default-features = false, optional = true } diff --git a/rollup/src/account.rs b/rollup/src/account.rs index c48e3b5..b2ea12e 100644 --- a/rollup/src/account.rs +++ b/rollup/src/account.rs @@ -47,7 +47,9 @@ impl AccountInformationVar { /// Convert the account information to bytes. #[tracing::instrument(target = "r1cs", skip(self))] pub fn to_bytes_le(&self) -> Vec> { - self.public_key.to_bytes_le().unwrap() + let mut result = self.public_key.to_bytes_le().unwrap(); + result.extend_from_slice(&self.balance.to_bytes_le()); + result } } diff --git a/rollup/src/ledger.rs b/rollup/src/ledger.rs index e69b6ec..0299028 100644 --- a/rollup/src/ledger.rs +++ b/rollup/src/ledger.rs @@ -1,9 +1,5 @@ use crate::ConstraintF; -use ark_crypto_primitives::crh::injective_map::constraints::{ - PedersenCRHCompressorGadget, PedersenTwoToOneCRHCompressorGadget, TECompressorGadget, -}; -use ark_crypto_primitives::crh::{injective_map::TECompressor, CRHScheme, TwoToOneCRHScheme}; use ark_crypto_primitives::crh::{CRHSchemeGadget, TwoToOneCRHSchemeGadget}; use ark_crypto_primitives::merkle_tree::constraints::PathVar; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; @@ -77,22 +73,6 @@ impl AllocVar for AmountVar { } } -pub type TwoToOneHashGadget = PedersenTwoToOneCRHCompressorGadget< - EdwardsProjective, - TECompressor, - TwoToOneWindow, - EdwardsVar, - TECompressorGadget, ->; - -pub type LeafHashGadget = PedersenCRHCompressorGadget< - EdwardsProjective, - TECompressor, - LeafWindow, - EdwardsVar, - TECompressorGadget, ->; - pub type AccRootVar = >::OutputVar; diff --git a/rollup/src/lib.rs b/rollup/src/lib.rs index 49c85de..f64b462 100644 --- a/rollup/src/lib.rs +++ b/rollup/src/lib.rs @@ -1,4 +1,4 @@ -pub type ConstraintF = ark_bls12_381::Fr; +pub type ConstraintF = ark_ed_on_bls12_381::Fq; pub mod account; pub mod ledger; diff --git a/rollup/src/transaction.rs b/rollup/src/transaction.rs index 52c80b6..15091cd 100644 --- a/rollup/src/transaction.rs +++ b/rollup/src/transaction.rs @@ -130,11 +130,13 @@ impl TransactionVar { )?; // TODO: Uncomment the following - sender_exists - .nand(&sender_updated_correctly)? - .nand(&recipient_exists)? - .nand(&recipient_updated_correctly)? - .nand(&sig_verifies) + let val = sender_exists + & sender_updated_correctly + & recipient_exists + & recipient_updated_correctly + & sig_verifies; + + Ok(val) } } @@ -259,6 +261,7 @@ impl ConstraintSynthesizer for UnaryRollup { let initial_root = AccRootVar::new_input(ark_relations::ns!(cs, "Initial root"), || { Ok(self.initial_root) })?; + // Declare the final root as a public input. let final_root = AccRootVar::new_input(ark_relations::ns!(cs, "Final root"), || Ok(self.final_root))?; @@ -322,6 +325,7 @@ mod test { use ark_relations::r1cs::{ ConstraintLayer, ConstraintSynthesizer, ConstraintSystem, TracingMode::OnlyConstraints, }; + use ark_simple_payments::ledger::{Amount, Parameters, State}; use ark_simple_payments::transaction::Transaction; use tracing_subscriber::layer::SubscriberExt; @@ -333,11 +337,7 @@ mod test { let _guard = tracing::subscriber::set_default(subscriber); let cs = ConstraintSystem::new_ref(); rollup.generate_constraints(cs.clone()).unwrap(); - let result = cs.is_satisfied().unwrap(); - if !result { - println!("{:?}", cs.which_is_unsatisfied()); - } - result + cs.is_satisfied().unwrap() } #[test] @@ -345,6 +345,7 @@ mod test { let mut rng = ark_std::test_rng(); let pp = Parameters::sample(&mut rng); let mut state = State::new(32, &pp); + // Let's make an account for Alice. let (alice_id, _alice_pk, alice_sk) = state.sample_keys_and_register(&pp, &mut rng).unwrap(); @@ -362,6 +363,7 @@ mod test { let rollup = UnaryRollup::with_state_and_transaction(pp.clone(), tx1, &mut temp_state, true) .unwrap(); + assert!(test_cs(rollup)); let mut temp_state = state.clone(); diff --git a/simple-payments/src/account.rs b/simple-payments/src/account.rs index ddec198..23dbc2c 100644 --- a/simple-payments/src/account.rs +++ b/simple-payments/src/account.rs @@ -40,7 +40,7 @@ impl AccountInformation { pub fn to_bytes_le(&self) -> Vec { let mut public_key_bytes = Vec::new(); self.public_key - .serialize_compressed(&mut public_key_bytes) + .serialize_uncompressed(&mut public_key_bytes) .unwrap(); public_key_bytes.extend_from_slice(&self.balance.to_bytes_le()); diff --git a/simple-payments/src/ledger.rs b/simple-payments/src/ledger.rs index f0e2c36..13ad948 100644 --- a/simple-payments/src/ledger.rs +++ b/simple-payments/src/ledger.rs @@ -73,8 +73,8 @@ pub struct TwoToOneWindow; // `WINDOW_SIZE * NUM_WINDOWS` = 2 * 256 bits = enough for hashing two outputs. impl pedersen::Window for TwoToOneWindow { - const WINDOW_SIZE: usize = 128; - const NUM_WINDOWS: usize = 4; + const WINDOW_SIZE: usize = 4; + const NUM_WINDOWS: usize = 128; } pub type LeafHash = PedersenCRHCompressor; @@ -91,8 +91,8 @@ pub struct LeafWindow; // `WINDOW_SIZE * NUM_WINDOWS` = 2 * 256 bits = enough for hashing two outputs. impl pedersen::Window for LeafWindow { - const WINDOW_SIZE: usize = 144; - const NUM_WINDOWS: usize = 4; + const WINDOW_SIZE: usize = 4; + const NUM_WINDOWS: usize = 144; } pub type ConstraintF = ark_ed_on_bls12_381::Fq; diff --git a/simple-payments/src/random_oracle/blake2s/constraints.rs b/simple-payments/src/random_oracle/blake2s/constraints.rs index ff32188..f853d07 100644 --- a/simple-payments/src/random_oracle/blake2s/constraints.rs +++ b/simple-payments/src/random_oracle/blake2s/constraints.rs @@ -26,7 +26,7 @@ impl RandomOracleGadget for ROGadget { input_bits.extend_from_slice(&byte.to_bits_le()?); } let mut result = Vec::new(); - for int in evaluate_blake2s(&input_bits)?.into_iter() { + for int in evaluate_blake2s(&input_bits)?.iter() { let chunk = int.to_bytes_le().unwrap(); result.extend_from_slice(&chunk); } diff --git a/simple-payments/src/signature/constraints.rs b/simple-payments/src/signature/constraints.rs index 2ccba36..068599c 100644 --- a/simple-payments/src/signature/constraints.rs +++ b/simple-payments/src/signature/constraints.rs @@ -2,7 +2,6 @@ use crate::signature::SignatureScheme; use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; -use tracing_subscriber::layer::SubscriberExt; pub trait SigVerifyGadget { type ParametersVar: AllocVar + Clone; diff --git a/simple-payments/src/signature/schnorr/constraints.rs b/simple-payments/src/signature/schnorr/constraints.rs index 2daf4cd..6e44f6f 100644 --- a/simple-payments/src/signature/schnorr/constraints.rs +++ b/simple-payments/src/signature/schnorr/constraints.rs @@ -1,7 +1,6 @@ use ark_ec::CurveGroup; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::ConstraintSystemRef; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_std::vec::Vec; @@ -189,7 +188,7 @@ where let mut response_bytes = Vec::new(); val.borrow() .prover_response - .serialize_compressed(&mut response_bytes) + .serialize_uncompressed(&mut response_bytes) .unwrap(); let challenge_bytes = val.borrow().verifier_challenge; let mut prover_response = Vec::>>::new(); diff --git a/simple-payments/src/signature/schnorr/mod.rs b/simple-payments/src/signature/schnorr/mod.rs index 9662a80..a58417a 100644 --- a/simple-payments/src/signature/schnorr/mod.rs +++ b/simple-payments/src/signature/schnorr/mod.rs @@ -3,7 +3,7 @@ use ark_crypto_primitives::Error; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{ fields::{Field, PrimeField}, - BigInteger, ToConstraintField, UniformRand, + ToConstraintField, UniformRand, }; use ark_serialize::CanonicalSerialize; use ark_std::rand::Rng; diff --git a/simple-payments/src/transaction.rs b/simple-payments/src/transaction.rs index 94a9f5f..ee3791c 100644 --- a/simple-payments/src/transaction.rs +++ b/simple-payments/src/transaction.rs @@ -53,6 +53,7 @@ impl Transaction { .account_merkle_tree .generate_proof(self.sender.0 as usize) .expect("path should exist"); + path.verify( ¶meters.leaf_crh_params, ¶meters.two_to_one_crh_params, From 121ef71fc81b28fc159bccafec5324ed09e34882 Mon Sep 17 00:00:00 2001 From: rac-sri Date: Sun, 13 Jul 2025 00:25:03 +0530 Subject: [PATCH 09/10] feat: add todos --- merkle-tree-example/src/constraints.rs | 11 ++---- rollup/src/transaction.rs | 48 +++++++------------------- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/merkle-tree-example/src/constraints.rs b/merkle-tree-example/src/constraints.rs index 4f6c180..e33641d 100644 --- a/merkle-tree-example/src/constraints.rs +++ b/merkle-tree-example/src/constraints.rs @@ -56,14 +56,9 @@ impl ConstraintSynthesizer for MerkleTreeVerification { // Hint: look at https://github.com/arkworks-rs/crypto-primitives/blob/6be606259eab0aec010015e2cfd45e4f134cd9bf/src/merkle_tree/constraints.rs#L135 // TODO: FILL IN THE BLANK! - let is_member = path.verify_membership( - &leaf_crh_params, - &two_to_one_crh_params, - &root, - &leaf_bytes.as_slice(), - )?; - - is_member.enforce_equal(&Boolean::TRUE)?; + // let is_member = XYZ + // + // is_member.enforce_equal(&Boolean::TRUE)?; Ok(()) } diff --git a/rollup/src/transaction.rs b/rollup/src/transaction.rs index 15091cd..cbdd0c4 100644 --- a/rollup/src/transaction.rs +++ b/rollup/src/transaction.rs @@ -79,64 +79,40 @@ impl TransactionVar { ) -> Result, SynthesisError> { // Verify the signature against the sender pubkey. // TODO: FILL IN THE BLANK - let sig_verifies = - self.verify_signature(¶meters.sig_params, &pre_sender_acc_info.public_key)?; + // let sig_verifies = ???; // Compute the new sender balance. let mut post_sender_acc_info = pre_sender_acc_info.clone(); // TODO: Safely subtract amount sent from the sender's balance - post_sender_acc_info.balance = post_sender_acc_info.balance.checked_sub(&self.amount)?; + // post_sender_acc_info.balance = ???; // TODO: Compute the new receiver balance, ensure its overflow safe. let mut post_recipient_acc_info = pre_recipient_acc_info.clone(); - post_recipient_acc_info.balance = - post_recipient_acc_info.balance.checked_add(&self.amount)?; + // post_recipient_acc_info.balance = ??? // Check that the pre-tx sender account information is correct with // respect to `pre_tx_root`, and that the post-tx sender account // information is correct with respect to `post_tx_root`. // HINT: Use the path structs // TODO: FILL IN THE FOLLOWING - let sender_exists = pre_sender_path.verify_membership( - ¶meters.leaf_crh_params, - ¶meters.two_to_one_crh_params, - &pre_root, - &pre_sender_acc_info.to_bytes_le().as_slice(), - )?; + // let sender_exists = ??? - let sender_updated_correctly = post_sender_path.verify_membership( - ¶meters.leaf_crh_params, - ¶meters.two_to_one_crh_params, - &post_root, - &post_sender_acc_info.to_bytes_le().as_slice(), - )?; + // let sender_updated_correctly = ??? // Check that the pre-tx recipient account information is correct with // respect to `pre_tx_root`, and that the post-tx recipient account // information is correct with respect to `post_tx_root`. // TODO: FILL IN THE FOLLOWING - let recipient_exists = pre_recipient_path.verify_membership( - ¶meters.leaf_crh_params, - ¶meters.two_to_one_crh_params, - &pre_root, - &pre_recipient_acc_info.to_bytes_le().as_slice(), - )?; - - let recipient_updated_correctly = post_recipient_path.verify_membership( - ¶meters.leaf_crh_params, - ¶meters.two_to_one_crh_params, - &post_root, - &post_recipient_acc_info.to_bytes_le().as_slice(), - )?; + // let recipient_exists = ??? // TODO: Uncomment the following - let val = sender_exists - & sender_updated_correctly - & recipient_exists - & recipient_updated_correctly - & sig_verifies; + // sender_exists + // & sender_updated_correctly + // & recipient_exists + // & recipient_updated_correctly + // & sig_verifies - Ok(val) + Err(SynthesisError::Unsatisfiable) } } From e3e12579050de01a489902a158e03baae15202eb Mon Sep 17 00:00:00 2001 From: rac-sri Date: Sun, 13 Jul 2025 00:30:44 +0530 Subject: [PATCH 10/10] feat: add todos --- rollup/src/rollup.rs | 38 ++++++++++++++++---------------------- rollup/src/transaction.rs | 2 ++ 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/rollup/src/rollup.rs b/rollup/src/rollup.rs index 9eb64e6..08fa79b 100644 --- a/rollup/src/rollup.rs +++ b/rollup/src/rollup.rs @@ -199,10 +199,7 @@ impl ConstraintSynthesizer for Rollup })?; // ... and authentication path after the update. // TODO: Fill in the following - let sender_post_path = - AccPathVar::new_witness(ark_relations::ns!(cs, "Sender Post-Path"), || { - sender_post_path.ok_or(SynthesisError::AssignmentMissing) - })?; + // let sender_post_path = ??? // Declare the recipient's initial account balance... let recipient_acc_info = AccountInformationVar::new_witness( @@ -217,10 +214,7 @@ impl ConstraintSynthesizer for Rollup // ... and authentication path after the update. // TODO: Fill in the following - let recipient_post_path = - AccPathVar::new_witness(ark_relations::ns!(cs, "Recipient Post-Path"), || { - recipient_post_path.ok_or(SynthesisError::AssignmentMissing) - })?; + // let recipient_post_path = ??? // Declare the state root before the transaction... let pre_tx_root = @@ -235,29 +229,29 @@ impl ConstraintSynthesizer for Rollup // Enforce that the state root after the previous transaction equals // the starting state root for this transaction - prev_root.enforce_equal(&pre_tx_root)?; + // TODO: Write this // Validate that the transaction signature and amount is correct. // TODO: Uncomment this - tx.validate( - &ledger_params, - &sender_acc_info, - &sender_pre_path, - &sender_post_path, - &recipient_acc_info, - &recipient_pre_path, - &recipient_post_path, - &pre_tx_root, - &post_tx_root, - )? - .enforce_equal(&Boolean::TRUE)?; + // tx.validate( + // &ledger_params, + // &sender_acc_info, + // &sender_pre_path, + // &sender_post_path, + // &recipient_acc_info, + // &recipient_pre_path, + // &recipient_post_path, + // &pre_tx_root, + // &post_tx_root, + // )? + // .enforce_equal(&Boolean::TRUE)?; // Set the root for the next transaction. prev_root = post_tx_root; } // Check that the final root is consistent with the root computed after // applying all state transitions - prev_root.enforce_equal(&final_root)?; + // TODO: implement this Ok(()) } } diff --git a/rollup/src/transaction.rs b/rollup/src/transaction.rs index cbdd0c4..2305138 100644 --- a/rollup/src/transaction.rs +++ b/rollup/src/transaction.rs @@ -111,7 +111,9 @@ impl TransactionVar { // & recipient_exists // & recipient_updated_correctly // & sig_verifies + // Ok(val) + // TODO: Comment the following Err(SynthesisError::Unsatisfiable) } }