From e57566d6749608ecc1371cc57586fa3a837385b1 Mon Sep 17 00:00:00 2001 From: David Rusu Date: Wed, 17 Jul 2024 21:54:53 +0400 Subject: [PATCH] goas: unlink input and output balance commitments --- goas/cl/cl/src/balance.rs | 183 ++++++++++------------------------- goas/cl/cl/src/bundle.rs | 80 +++++++-------- goas/cl/cl/src/input.rs | 33 +++++-- goas/cl/cl/src/note.rs | 96 ++++++++++++------ goas/cl/cl/src/output.rs | 41 +++++--- goas/cl/cl/src/partial_tx.rs | 39 ++++---- 6 files changed, 225 insertions(+), 247 deletions(-) diff --git a/goas/cl/cl/src/balance.rs b/goas/cl/cl/src/balance.rs index b09202d..ce63c29 100644 --- a/goas/cl/cl/src/balance.rs +++ b/goas/cl/cl/src/balance.rs @@ -2,6 +2,9 @@ use curve25519_dalek::{ristretto::RistrettoPoint, traits::VartimeMultiscalarMul, use lazy_static::lazy_static; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; + +use crate::NoteWitness; + lazy_static! { // Precompute of `` static ref PEDERSON_COMMITMENT_BLINDING_POINT: RistrettoPoint = crate::crypto::hash_to_curve(b"NOMOS_CL_PEDERSON_COMMITMENT_BLINDING"); @@ -11,40 +14,28 @@ lazy_static! { pub struct Balance(pub RistrettoPoint); #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] -pub struct BalanceWitness { - pub value: u64, - pub unit: RistrettoPoint, - pub blinding: Scalar, -} +pub struct BalanceWitness(pub Scalar); impl Balance { pub fn to_bytes(&self) -> [u8; 32] { - self.0.compress().to_bytes().into() + self.0.compress().to_bytes() } } impl BalanceWitness { - pub fn new(value: u64, unit: impl Into, blinding: Scalar) -> Self { - Self { - value, - unit: unit_point(&unit.into()), - blinding, - } + pub fn new(blinding: Scalar) -> Self { + Self(blinding) } - pub fn random(value: u64, unit: impl Into, mut rng: impl CryptoRngCore) -> Self { - Self::new(value, unit, Scalar::random(&mut rng)) + pub fn random(mut rng: impl CryptoRngCore) -> Self { + Self::new(Scalar::random(&mut rng)) } - pub fn commit(&self) -> Balance { - Balance(balance(self.value, self.unit, self.blinding)) + pub fn commit(&self, note: &NoteWitness) -> Balance { + Balance(balance(note.value, note.unit, self.0)) } } -pub fn unit_point(unit: &str) -> RistrettoPoint { - crate::crypto::hash_to_curve(unit.as_bytes()) -} - pub fn balance(value: u64, unit: RistrettoPoint, blinding: Scalar) -> RistrettoPoint { let value_scalar = Scalar::from(value); // can vartime leak the number of cycles through the stark proof? @@ -54,97 +45,6 @@ pub fn balance(value: u64, unit: RistrettoPoint, blinding: Scalar) -> RistrettoP ) } -// mod serde_scalar { -// use super::Scalar; -// use serde::de::{self, Visitor}; -// use serde::{Deserializer, Serializer}; -// use std::fmt; - -// // Serialize a SubgroupPoint by converting it to bytes. -// pub fn serialize(scalar: &Scalar, serializer: S) -> Result -// where -// S: Serializer, -// { -// let bytes = scalar.to_bytes(); -// serializer.serialize_bytes(&bytes) -// } - -// // Deserialize a SubgroupPoint by converting it from bytes. -// pub fn deserialize<'de, D>(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// struct BytesVisitor; - -// impl<'de> Visitor<'de> for BytesVisitor { -// type Value = Scalar; - -// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -// formatter.write_str("a valid Scalar in byte representation") -// } - -// fn visit_bytes(self, v: &[u8]) -> Result -// where -// E: de::Error, -// { -// let mut bytes = ::Repr::default(); -// assert_eq!(bytes.len(), v.len()); -// bytes.copy_from_slice(v); - -// Ok(Scalar::from_bytes(&bytes).unwrap()) -// } -// } - -// deserializer.deserialize_bytes(BytesVisitor) -// } -// } - -// mod serde_point { -// use super::SubgroupPoint; -// use group::GroupEncoding; -// use serde::de::{self, Visitor}; -// use serde::{Deserializer, Serializer}; -// use std::fmt; - -// // Serialize a SubgroupPoint by converting it to bytes. -// pub fn serialize(point: &SubgroupPoint, serializer: S) -> Result -// where -// S: Serializer, -// { -// let bytes = point.to_bytes(); -// serializer.serialize_bytes(&bytes) -// } - -// // Deserialize a SubgroupPoint by converting it from bytes. -// pub fn deserialize<'de, D>(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// struct BytesVisitor; - -// impl<'de> Visitor<'de> for BytesVisitor { -// type Value = SubgroupPoint; - -// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -// formatter.write_str("a valid SubgroupPoint in byte representation") -// } - -// fn visit_bytes(self, v: &[u8]) -> Result -// where -// E: de::Error, -// { -// let mut bytes = ::Repr::default(); -// assert_eq!(bytes.len(), v.len()); -// bytes.copy_from_slice(v); - -// Ok(SubgroupPoint::from_bytes(&bytes).unwrap()) -// } -// } - -// deserializer.deserialize_bytes(BytesVisitor) -// } -// } - #[cfg(test)] mod test { @@ -165,52 +65,67 @@ mod test { fn test_balance_zero_unitless() { // Zero is the same across all units let mut rng = rand::thread_rng(); - let r = Scalar::random(&mut rng); + let b = BalanceWitness::random(&mut rng); assert_eq!( - BalanceWitness::new(0, "NMO", r).commit(), - BalanceWitness::new(0, "ETH", r).commit(), + b.commit(&NoteWitness::basic(0, "NMO")), + b.commit(&NoteWitness::basic(0, "ETH")), ); } #[test] fn test_balance_blinding() { // balances are blinded - let r1 = Scalar::from(12u32); - let r2 = Scalar::from(8u32); - let a_w = BalanceWitness::new(10, "NMO", r1); - let b_w = BalanceWitness::new(10, "NMO", r2); - let a = a_w.commit(); - let b = b_w.commit(); + let r_a = Scalar::from(12u32); + let r_b = Scalar::from(8u32); + let bal_a = BalanceWitness::new(r_a); + let bal_b = BalanceWitness::new(r_b); + + let note = NoteWitness::basic(10, "NMO"); + + let a = bal_a.commit(¬e); + let b = bal_b.commit(¬e); + assert_ne!(a, b); - assert_eq!(a.0 - b.0, BalanceWitness::new(0, "NMO", r1 - r2).commit().0); + + let diff_note = NoteWitness::basic(0, "NMO"); + assert_eq!( + a.0 - b.0, + BalanceWitness::new(r_a - r_b).commit(&diff_note).0 + ); } #[test] fn test_balance_units() { // Unit's differentiate between values. - let r = Scalar::from(1337u32); - let nmo = BalanceWitness::new(10, "NMO", r); - let eth = BalanceWitness::new(10, "ETH", r); - assert_ne!(nmo.commit(), eth.commit()); + let b = BalanceWitness::new(Scalar::from(1337u32)); + + let nmo = NoteWitness::basic(10, "NMO"); + let eth = NoteWitness::basic(10, "ETH"); + assert_ne!(b.commit(&nmo), b.commit(ð)); } #[test] fn test_balance_homomorphism() { let mut rng = rand::thread_rng(); - let r1 = Scalar::random(&mut rng); - let r2 = Scalar::random(&mut rng); - let ten = BalanceWitness::new(10, "NMO", 0u32.into()); - let eight = BalanceWitness::new(8, "NMO", 0u32.into()); - let two = BalanceWitness::new(2, "NMO", 0u32.into()); + let b1 = BalanceWitness::random(&mut rng); + let b2 = BalanceWitness::random(&mut rng); + let b_zero = BalanceWitness::new(Scalar::ZERO); + + let ten = NoteWitness::basic(10, "NMO"); + let eight = NoteWitness::basic(8, "NMO"); + let two = NoteWitness::basic(2, "NMO"); + let zero = NoteWitness::basic(0, "NMO"); // Values of same unit are homomorphic - assert_eq!(ten.commit().0 - eight.commit().0, two.commit().0); + assert_eq!( + (b1.commit(&ten).0 - b1.commit(&eight).0).compress(), + b_zero.commit(&two).0.compress() + ); // Blinding factors are also homomorphic. assert_eq!( - BalanceWitness::new(10, "NMO", r1).commit().0 - - BalanceWitness::new(10, "NMO", r2).commit().0, - BalanceWitness::new(0, "NMO", r1 - r2).commit().0 + b1.commit(&ten).0 - b2.commit(&ten).0, + BalanceWitness::new(b1.0 - b2.0).commit(&zero).0 ); } } diff --git a/goas/cl/cl/src/bundle.rs b/goas/cl/cl/src/bundle.rs index 0aec2f2..137ff4d 100644 --- a/goas/cl/cl/src/bundle.rs +++ b/goas/cl/cl/src/bundle.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; -use curve25519_dalek::{constants::RISTRETTO_BASEPOINT_POINT, ristretto::RistrettoPoint, Scalar}; +use curve25519_dalek::{constants::RISTRETTO_BASEPOINT_POINT, ristretto::RistrettoPoint}; -use crate::partial_tx::PartialTx; +use crate::{partial_tx::PartialTx, BalanceWitness}; /// The transaction bundle is a collection of partial transactions. /// The goal in bundling transactions is to produce a set of partial transactions @@ -15,7 +15,7 @@ pub struct Bundle { #[derive(Debug, Clone)] pub struct BundleWitness { - pub balance_blinding: Scalar, + pub balance: BalanceWitness, } impl Bundle { @@ -23,9 +23,8 @@ impl Bundle { self.partials.iter().map(|ptx| ptx.balance()).sum() } - pub fn is_balanced(&self, balance_blinding_witness: Scalar) -> bool { - self.balance() - == crate::balance::balance(0, RISTRETTO_BASEPOINT_POINT, balance_blinding_witness) + pub fn is_balanced(&self, witness: BalanceWitness) -> bool { + self.balance() == crate::balance::balance(0, RISTRETTO_BASEPOINT_POINT, witness.0) } } @@ -42,15 +41,20 @@ mod test { fn test_bundle_balance() { let mut rng = rand::thread_rng(); - let nmo_10_in = - InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); - let eth_23_in = - InputWitness::random(NoteWitness::new(23, "ETH", [0u8; 32], &mut rng), &mut rng); - let crv_4840_out = OutputWitness::random( - NoteWitness::new(4840, "CRV", [0u8; 32], &mut rng), - NullifierSecret::random(&mut rng).commit(), // transferring to a random owner - &mut rng, - ); + let nf_a = NullifierSecret::random(&mut rng); + let nf_b = NullifierSecret::random(&mut rng); + let nf_c = NullifierSecret::random(&mut rng); + + let nmo_10_utxo = + OutputWitness::random(NoteWitness::basic(10, "NMO"), nf_a.commit(), &mut rng); + let nmo_10_in = InputWitness::random(nmo_10_utxo, nf_a, &mut rng); + + let eth_23_utxo = + OutputWitness::random(NoteWitness::basic(23, "ETH"), nf_b.commit(), &mut rng); + let eth_23_in = InputWitness::random(eth_23_utxo, nf_b, &mut rng); + + let crv_4840_out = + OutputWitness::random(NoteWitness::basic(4840, "CRV"), nf_c.commit(), &mut rng); let ptx_unbalanced = PartialTxWitness { inputs: vec![nmo_10_in.clone(), eth_23_in.clone()], @@ -58,42 +62,31 @@ mod test { }; let bundle_witness = BundleWitness { - balance_blinding: crv_4840_out.note.balance.blinding - - nmo_10_in.note.balance.blinding - - eth_23_in.note.balance.blinding, + balance: BalanceWitness::new( + crv_4840_out.balance.0 - nmo_10_in.balance.0 - eth_23_in.balance.0, + ), }; let mut bundle = Bundle { partials: vec![PartialTx::from_witness(ptx_unbalanced)], }; - assert!(!bundle.is_balanced(bundle_witness.balance_blinding)); + assert!(!bundle.is_balanced(bundle_witness.balance)); assert_eq!( bundle.balance(), - crate::balance::balance( - 4840, - hash_to_curve(b"CRV"), - crv_4840_out.note.balance.blinding - ) - (crate::balance::balance( - 10, - hash_to_curve(b"NMO"), - nmo_10_in.note.balance.blinding - ) + crate::balance::balance( - 23, - hash_to_curve(b"ETH"), - eth_23_in.note.balance.blinding - )) + crate::balance::balance(4840, hash_to_curve(b"CRV"), crv_4840_out.balance.0) + - (crate::balance::balance(10, hash_to_curve(b"NMO"), nmo_10_in.balance.0) + + crate::balance::balance(23, hash_to_curve(b"ETH"), eth_23_in.balance.0)) ); - let crv_4840_in = - InputWitness::random(NoteWitness::new(4840, "CRV", [0u8; 32], &mut rng), &mut rng); + let crv_4840_in = InputWitness::random(crv_4840_out, nf_c, &mut rng); let nmo_10_out = OutputWitness::random( - NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), + NoteWitness::basic(10, "NMO"), NullifierSecret::random(&mut rng).commit(), // transferring to a random owner &mut rng, ); let eth_23_out = OutputWitness::random( - NoteWitness::new(23, "ETH", [0u8; 32], &mut rng), + NoteWitness::basic(23, "ETH"), NullifierSecret::random(&mut rng).commit(), // transferring to a random owner &mut rng, ); @@ -106,11 +99,12 @@ mod test { })); let witness = BundleWitness { - balance_blinding: -nmo_10_in.note.balance.blinding - eth_23_in.note.balance.blinding - + crv_4840_out.note.balance.blinding - - crv_4840_in.note.balance.blinding - + nmo_10_out.note.balance.blinding - + eth_23_out.note.balance.blinding, + balance: BalanceWitness::new( + -nmo_10_in.balance.0 - eth_23_in.balance.0 + crv_4840_out.balance.0 + - crv_4840_in.balance.0 + + nmo_10_out.balance.0 + + eth_23_out.balance.0, + ), }; assert_eq!( @@ -118,10 +112,10 @@ mod test { crate::balance::balance( 0, curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT, - witness.balance_blinding + witness.balance.0 ) ); - assert!(bundle.is_balanced(witness.balance_blinding)); + assert!(bundle.is_balanced(witness.balance)); } } diff --git a/goas/cl/cl/src/input.rs b/goas/cl/cl/src/input.rs index dde6f36..c2d53ee 100644 --- a/goas/cl/cl/src/input.rs +++ b/goas/cl/cl/src/input.rs @@ -6,8 +6,9 @@ use crate::{ balance::Balance, note::{DeathCommitment, NoteWitness}, nullifier::{Nullifier, NullifierNonce, NullifierSecret}, + BalanceWitness, }; -use rand_core::RngCore; +use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] @@ -20,30 +21,44 @@ pub struct Input { #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct InputWitness { pub note: NoteWitness, + pub utxo_balance: BalanceWitness, + pub balance: BalanceWitness, pub nf_sk: NullifierSecret, pub nonce: NullifierNonce, } impl InputWitness { - pub fn random(note: NoteWitness, mut rng: impl RngCore) -> Self { + pub fn random( + output: crate::OutputWitness, + nf_sk: NullifierSecret, + mut rng: impl CryptoRngCore, + ) -> Self { + assert_eq!(nf_sk.commit(), output.nf_pk); Self { - note, - nf_sk: NullifierSecret::random(&mut rng), - nonce: NullifierNonce::random(&mut rng), + note: output.note, + utxo_balance: output.balance, + balance: BalanceWitness::random(&mut rng), + nf_sk, + nonce: output.nonce, } } + pub fn nullifier(&self) -> Nullifier { + Nullifier::new(self.nf_sk, self.nonce) + } + pub fn commit(&self) -> Input { Input { - nullifier: Nullifier::new(self.nf_sk, self.nonce), - balance: self.note.balance(), + nullifier: self.nullifier(), + balance: self.balance.commit(&self.note), death_cm: self.note.death_commitment(), } } - pub fn to_output_witness(&self) -> crate::OutputWitness { + pub fn to_output(&self) -> crate::OutputWitness { crate::OutputWitness { - note: self.note.clone(), + note: self.note, + balance: self.utxo_balance, nf_pk: self.nf_sk.commit(), nonce: self.nonce, } diff --git a/goas/cl/cl/src/note.rs b/goas/cl/cl/src/note.rs index 0beed54..44ef951 100644 --- a/goas/cl/cl/src/note.rs +++ b/goas/cl/cl/src/note.rs @@ -1,11 +1,8 @@ -use rand_core::CryptoRngCore; +use curve25519_dalek::RistrettoPoint; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; -use crate::{ - balance::{Balance, BalanceWitness}, - nullifier::{NullifierCommitment, NullifierNonce}, -}; +use crate::nullifier::{NullifierCommitment, NullifierNonce}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct DeathCommitment(pub [u8; 32]); @@ -19,6 +16,10 @@ pub fn death_commitment(death_constraint: &[u8]) -> DeathCommitment { DeathCommitment(death_cm) } +pub fn unit_point(unit: &str) -> RistrettoPoint { + crate::crypto::hash_to_curve(unit.as_bytes()) +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct NoteCommitment([u8; 32]); @@ -32,32 +33,38 @@ impl NoteCommitment { #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] pub struct NoteWitness { - pub balance: BalanceWitness, + pub value: u64, + pub unit: RistrettoPoint, pub death_constraint: [u8; 32], // death constraint verification key pub state: [u8; 32], } impl NoteWitness { - pub fn new( - value: u64, - unit: impl Into, - state: [u8; 32], - rng: impl CryptoRngCore, - ) -> Self { + pub fn new(value: u64, unit: impl Into, state: [u8; 32]) -> Self { Self { - balance: BalanceWitness::random(value, unit, rng), + value, + unit: unit_point(&unit.into()), death_constraint: [0u8; 32], state, } } + pub fn basic(value: u64, unit: impl Into) -> Self { + Self { + value, + unit: unit_point(&unit.into()), + death_constraint: [0u8; 32], + state: [0u8; 32], + } + } + pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment { let mut hasher = Sha256::new(); hasher.update(b"NOMOS_CL_NOTE_COMMIT"); // COMMIT TO BALANCE - hasher.update(self.balance.value.to_le_bytes()); - hasher.update(self.balance.unit.compress().to_bytes()); + hasher.update(self.value.to_le_bytes()); + hasher.update(self.unit.compress().to_bytes()); // Important! we don't commit to the balance blinding factor as that may make the notes linkable. // COMMIT TO STATE @@ -74,10 +81,6 @@ impl NoteWitness { NoteCommitment(commit_bytes) } - pub fn balance(&self) -> Balance { - self.balance.commit() - } - pub fn death_commitment(&self) -> DeathCommitment { death_commitment(&self.death_constraint) } @@ -90,18 +93,57 @@ mod test { use super::*; #[test] - fn test_note_commitments_dont_commit_to_balance_blinding() { + fn test_note_commit_permutations() { let mut rng = rand::thread_rng(); - let n1 = NoteWitness::new(12, "NMO", [0u8; 32], &mut rng); - let n2 = NoteWitness::new(12, "NMO", [0u8; 32], &mut rng); let nf_pk = NullifierSecret::random(&mut rng).commit(); - let nonce = NullifierNonce::random(&mut rng); + let nf_nonce = NullifierNonce::random(&mut rng); - // Balance blinding factors are different. - assert_ne!(n1.balance.blinding, n2.balance.blinding); + let reference_note = NoteWitness::new(32, "NMO", [0u8; 32]); - // But their commitments are the same. - assert_eq!(n1.commit(nf_pk, nonce), n2.commit(nf_pk, nonce)); + // different notes under same nullifier produce different commitments + let mutation_tests = [ + NoteWitness { + value: 12, + ..reference_note + }, + NoteWitness { + unit: unit_point("ETH"), + ..reference_note + }, + NoteWitness { + death_constraint: [1u8; 32], + ..reference_note + }, + NoteWitness { + state: [1u8; 32], + ..reference_note + }, + ]; + + for n in mutation_tests { + assert_ne!( + n.commit(nf_pk, nf_nonce), + reference_note.commit(nf_pk, nf_nonce) + ); + } + + // commitment to same note with different nullifiers produce different commitments + + let other_nf_pk = NullifierSecret::random(&mut rng).commit(); + let other_nf_nonce = NullifierNonce::random(&mut rng); + + assert_ne!( + reference_note.commit(nf_pk, nf_nonce), + reference_note.commit(other_nf_pk, nf_nonce) + ); + assert_ne!( + reference_note.commit(nf_pk, nf_nonce), + reference_note.commit(nf_pk, other_nf_nonce) + ); + assert_ne!( + reference_note.commit(nf_pk, nf_nonce), + reference_note.commit(other_nf_pk, other_nf_nonce) + ); } } diff --git a/goas/cl/cl/src/output.rs b/goas/cl/cl/src/output.rs index f7e2391..743f92d 100644 --- a/goas/cl/cl/src/output.rs +++ b/goas/cl/cl/src/output.rs @@ -1,4 +1,4 @@ -use rand_core::RngCore; +use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use crate::{ @@ -6,6 +6,7 @@ use crate::{ error::Error, note::{NoteCommitment, NoteWitness}, nullifier::{NullifierCommitment, NullifierNonce}, + BalanceWitness, }; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -14,17 +15,23 @@ pub struct Output { pub balance: Balance, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct OutputWitness { pub note: NoteWitness, + pub balance: BalanceWitness, pub nf_pk: NullifierCommitment, pub nonce: NullifierNonce, } impl OutputWitness { - pub fn random(note: NoteWitness, owner: NullifierCommitment, mut rng: impl RngCore) -> Self { + pub fn random( + note: NoteWitness, + owner: NullifierCommitment, + mut rng: impl CryptoRngCore, + ) -> Self { Self { note, + balance: BalanceWitness::random(&mut rng), nf_pk: owner, nonce: NullifierNonce::random(&mut rng), } @@ -34,10 +41,14 @@ impl OutputWitness { self.note.commit(self.nf_pk, self.nonce) } + pub fn commit_balance(&self) -> Balance { + self.balance.commit(&self.note) + } + pub fn commit(&self) -> Output { Output { note_comm: self.commit_note(), - balance: self.note.balance(), + balance: self.commit_balance(), } } } @@ -61,8 +72,7 @@ impl Output { // - balance == v * hash_to_curve(Unit) + blinding * H let witness = &proof.0; - self.note_comm == witness.note.commit(witness.nf_pk, witness.nonce) - && self.balance == witness.note.balance() + self.note_comm == witness.commit_note() && self.balance == witness.commit_balance() } pub fn to_bytes(&self) -> [u8; 64] { @@ -82,11 +92,12 @@ mod test { fn test_output_proof() { let mut rng = rand::thread_rng(); - let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); - let nf_pk = NullifierSecret::random(&mut rng).commit(); - let nonce = NullifierNonce::random(&mut rng); - - let witness = OutputWitness { note, nf_pk, nonce }; + let witness = OutputWitness { + note: NoteWitness::basic(10, "NMO"), + balance: BalanceWitness::random(&mut rng), + nf_pk: NullifierSecret::random(&mut rng).commit(), + nonce: NullifierNonce::random(&mut rng), + }; let output = witness.commit(); let proof = output.prove(&witness).unwrap(); @@ -95,11 +106,15 @@ mod test { let wrong_witnesses = [ OutputWitness { - note: NoteWitness::new(11, "NMO", [0u8; 32], &mut rng), + note: NoteWitness::basic(11, "NMO"), ..witness.clone() }, OutputWitness { - note: NoteWitness::new(10, "ETH", [0u8; 32], &mut rng), + note: NoteWitness::basic(10, "ETH"), + ..witness.clone() + }, + OutputWitness { + balance: BalanceWitness::random(&mut rng), ..witness.clone() }, OutputWitness { diff --git a/goas/cl/cl/src/partial_tx.rs b/goas/cl/cl/src/partial_tx.rs index 814a70f..85e11ab 100644 --- a/goas/cl/cl/src/partial_tx.rs +++ b/goas/cl/cl/src/partial_tx.rs @@ -1,6 +1,5 @@ -use rand_core::RngCore; -// use risc0_groth16::ProofJson; use curve25519_dalek::ristretto::RistrettoPoint; +use rand_core::RngCore; use serde::{Deserialize, Serialize}; use crate::input::{Input, InputWitness}; @@ -115,15 +114,20 @@ mod test { fn test_partial_tx_balance() { let mut rng = rand::thread_rng(); - let nmo_10 = - InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); - let eth_23 = - InputWitness::random(NoteWitness::new(23, "ETH", [0u8; 32], &mut rng), &mut rng); - let crv_4840 = OutputWitness::random( - NoteWitness::new(4840, "CRV", [0u8; 32], &mut rng), - NullifierSecret::random(&mut rng).commit(), // transferring to a random owner - &mut rng, - ); + let nf_a = NullifierSecret::random(&mut rng); + let nf_b = NullifierSecret::random(&mut rng); + let nf_c = NullifierSecret::random(&mut rng); + + let nmo_10_utxo = + OutputWitness::random(NoteWitness::basic(10, "NMO"), nf_a.commit(), &mut rng); + let nmo_10 = InputWitness::random(nmo_10_utxo, nf_a, &mut rng); + + let eth_23_utxo = + OutputWitness::random(NoteWitness::basic(23, "ETH"), nf_b.commit(), &mut rng); + let eth_23 = InputWitness::random(eth_23_utxo, nf_b, &mut rng); + + let crv_4840 = + OutputWitness::random(NoteWitness::basic(4840, "CRV"), nf_c.commit(), &mut rng); let ptx_witness = PartialTxWitness { inputs: vec![nmo_10.clone(), eth_23.clone()], @@ -134,16 +138,9 @@ mod test { assert_eq!( ptx.balance(), - crate::balance::balance(4840, hash_to_curve(b"CRV"), crv_4840.note.balance.blinding) - - (crate::balance::balance( - 10, - hash_to_curve(b"NMO"), - nmo_10.note.balance.blinding - ) + crate::balance::balance( - 23, - hash_to_curve(b"ETH"), - eth_23.note.balance.blinding - )) + crate::balance::balance(4840, hash_to_curve(b"CRV"), crv_4840.balance.0) + - (crate::balance::balance(10, hash_to_curve(b"NMO"), nmo_10.balance.0) + + crate::balance::balance(23, hash_to_curve(b"ETH"), eth_23.balance.0)) ); } }