From 8a97325d55134c6f7d6cdc38447547cfde2cc574 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 12 Nov 2024 16:18:47 +0100 Subject: [PATCH] Add Witnesses struct --- src/builder.rs | 9 +- src/circuit.rs | 21 ++-- src/circuit/circuit_vanilla.rs | 103 +++++++++-------- src/circuit/circuit_zsa.rs | 205 ++++++++++++++++++--------------- 4 files changed, 185 insertions(+), 153 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 7e3b8fee4..94bcb191e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -17,7 +17,7 @@ use crate::{ action::Action, address::Address, bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, - circuit::{Circuit, Instance, OrchardCircuit, Proof, ProvingKey}, + circuit::{Circuit, Instance, OrchardCircuit, Proof, ProvingKey, Witnesses}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, @@ -445,7 +445,12 @@ impl ActionInfo { parts: SigningParts { ak, alpha }, }, ), - Circuit::::from_action_context_unchecked(self.spend, note, alpha, self.rcv), + Circuit:: { + witnesses: Witnesses::from_action_context_unchecked( + self.spend, note, alpha, self.rcv, + ), + phantom: std::marker::PhantomData, + }, ) } } diff --git a/src/circuit.rs b/src/circuit.rs index b0be32ce7..65ce158ef 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -105,7 +105,7 @@ pub trait OrchardCircuit: Sized + Default { /// Wrapper for configure function of plonk::Circuit trait fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, layouter: impl Layouter, ) -> Result<(), plonk::Error>; @@ -128,13 +128,20 @@ impl plonk::Circuit for Circuit { config: Self::Config, layouter: impl Layouter, ) -> Result<(), plonk::Error> { - C::synthesize(self, config, layouter) + C::synthesize(&self.witnesses, config, layouter) } } /// The Orchard Action circuit. #[derive(Clone, Debug, Default)] pub struct Circuit { + pub(crate) witnesses: Witnesses, + pub(crate) phantom: std::marker::PhantomData, +} + +/// The Orchard Action witnesses +#[derive(Clone, Debug, Default)] +pub struct Witnesses { pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, pub(crate) pos: Value, pub(crate) g_d_old: Value, @@ -157,10 +164,9 @@ pub struct Circuit { pub(crate) rcv: Value, pub(crate) asset: Value, pub(crate) split_flag: Value, - phantom: std::marker::PhantomData, } -impl Circuit { +impl Witnesses { /// This constructor is public to enable creation of custom builders. /// If you are not creating a custom builder, use [`Builder`] to compose /// and authorize a transaction. @@ -181,7 +187,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Option> { + ) -> Option { (Rho::from_nf_old(spend.note.nullifier(&spend.fvk)) == output_note.rho()) .then(|| Self::from_action_context_unchecked(spend, output_note, alpha, rcv)) } @@ -191,7 +197,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Circuit { + ) -> Self { let sender_address = spend.note.recipient(); let rho_old = spend.note.rho(); let psi_old = spend.note.rseed().psi(&rho_old); @@ -204,7 +210,7 @@ impl Circuit { let psi_new = output_note.rseed().psi(&rho_new); let rcm_new = output_note.rseed().rcm(&rho_new); - Circuit { + Witnesses { path: Value::known(spend.merkle_path.auth_path()), pos: Value::known(spend.merkle_path.position()), g_d_old: Value::known(sender_address.g_d()), @@ -227,7 +233,6 @@ impl Circuit { rcv: Value::known(rcv), asset: Value::known(spend.note.asset()), split_flag: Value::known(spend.split_flag), - phantom: std::marker::PhantomData, } } } diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs index 7f756e322..a2ddc8ab4 100644 --- a/src/circuit/circuit_vanilla.rs +++ b/src/circuit/circuit_vanilla.rs @@ -28,7 +28,7 @@ use crate::{ circuit::derive_nullifier::gadgets::derive_nullifier, circuit::note_commit::gadgets::note_commit, circuit::value_commit_orchard::gadgets::value_commit_orchard, - circuit::Config, + circuit::{Config, Witnesses}, constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, orchard_flavor::OrchardVanilla, }; @@ -37,8 +37,8 @@ use super::{ commit_ivk::CommitIvkChip, gadget::{add_chip::AddChip, assign_free_advice}, note_commit::NoteCommitChip, - Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, - RK_X, RK_Y, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X, + RK_Y, }; impl OrchardCircuit for OrchardVanilla { @@ -235,7 +235,7 @@ impl OrchardCircuit for OrchardVanilla { #[allow(non_snake_case)] fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), plonk::Error> { @@ -620,6 +620,7 @@ mod tests { use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; + use crate::circuit::Witnesses; use crate::{ bundle::Flags, circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, @@ -658,29 +659,31 @@ mod tests { ( OrchardCircuitVanilla { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - // For non split note, psi_nf is equal to psi_old - psi_nf: Value::known(psi_old), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - asset: Value::known(spent_note.asset()), - split_flag: Value::known(false), + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, phantom: std::marker::PhantomData, }, Instance { @@ -858,28 +861,30 @@ mod tests { .unwrap(); let circuit = OrchardCircuitVanilla { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - psi_nf: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - asset: Value::unknown(), - split_flag: Value::unknown(), + witnesses: Witnesses { + path: Value::unknown(), + pos: Value::unknown(), + g_d_old: Value::unknown(), + pk_d_old: Value::unknown(), + v_old: Value::unknown(), + rho_old: Value::unknown(), + psi_old: Value::unknown(), + rcm_old: Value::unknown(), + cm_old: Value::unknown(), + psi_nf: Value::unknown(), + alpha: Value::unknown(), + ak: Value::unknown(), + nk: Value::unknown(), + rivk: Value::unknown(), + g_d_new: Value::unknown(), + pk_d_new: Value::unknown(), + v_new: Value::unknown(), + psi_new: Value::unknown(), + rcm_new: Value::unknown(), + rcv: Value::unknown(), + asset: Value::unknown(), + split_flag: Value::unknown(), + }, phantom: std::marker::PhantomData, }; halo2_proofs::dev::CircuitLayout::default() diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index f4985137c..bcf1c053f 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -33,15 +33,15 @@ use super::{ gadget::{add_chip::AddChip, assign_free_advice, assign_is_native_asset, assign_split_flag}, note_commit::NoteCommitChip, value_commit_orchard::ZsaValueCommitParams, - Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, - ENABLE_ZSA, NF_OLD, RK_X, RK_Y, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, ENABLE_ZSA, + NF_OLD, RK_X, RK_Y, }; use crate::{ circuit::commit_ivk::gadgets::commit_ivk, circuit::derive_nullifier::gadgets::derive_nullifier, circuit::note_commit::{gadgets::note_commit, ZsaNoteCommitParams}, circuit::value_commit_orchard::gadgets::value_commit_orchard, - circuit::Config, + circuit::{Config, Witnesses}, constants::OrchardFixedBasesFull, constants::{OrchardFixedBases, OrchardHashDomains}, note::AssetBase, @@ -322,7 +322,7 @@ impl OrchardCircuit for OrchardZSA { #[allow(non_snake_case)] fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), plonk::Error> { @@ -843,6 +843,7 @@ mod tests { use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; + use crate::circuit::Witnesses; use crate::{ builder::SpendInfo, bundle::Flags, @@ -883,29 +884,31 @@ mod tests { ( OrchardCircuitZSA { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(psi_old), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - // For non split note, psi_nf is equal to psi_old - psi_nf: Value::known(psi_old), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - asset: Value::known(spent_note.asset()), - split_flag: Value::known(false), + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(psi_old), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, phantom: std::marker::PhantomData, }, Instance { @@ -1084,28 +1087,30 @@ mod tests { .unwrap(); let circuit = OrchardCircuitZSA { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - psi_nf: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - asset: Value::unknown(), - split_flag: Value::unknown(), + witnesses: Witnesses { + path: Value::unknown(), + pos: Value::unknown(), + g_d_old: Value::unknown(), + pk_d_old: Value::unknown(), + v_old: Value::unknown(), + rho_old: Value::unknown(), + psi_old: Value::unknown(), + rcm_old: Value::unknown(), + cm_old: Value::unknown(), + psi_nf: Value::unknown(), + alpha: Value::unknown(), + ak: Value::unknown(), + nk: Value::unknown(), + rivk: Value::unknown(), + g_d_new: Value::unknown(), + pk_d_new: Value::unknown(), + v_new: Value::unknown(), + psi_new: Value::unknown(), + rcm_new: Value::unknown(), + rcv: Value::unknown(), + asset: Value::unknown(), + split_flag: Value::unknown(), + }, phantom: std::marker::PhantomData, }; halo2_proofs::dev::CircuitLayout::default() @@ -1222,7 +1227,15 @@ mod tests { }; ( - OrchardCircuitZSA::from_action_context_unchecked(spend_info, output_note, alpha, rcv), + OrchardCircuitZSA { + witnesses: Witnesses::from_action_context_unchecked( + spend_info, + output_note, + alpha, + rcv, + ), + phantom: std::marker::PhantomData, + }, Instance { anchor, cv_net, @@ -1293,28 +1306,30 @@ mod tests { // Set cm_old to be a random NoteCommitment // The proof should fail let circuit_wrong_cm_old = OrchardCircuitZSA { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: Value::known(random_note_commitment(&mut rng)), - psi_nf: circuit.psi_nf, - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: Value::known(random_note_commitment(&mut rng)), + psi_nf: circuit.witnesses.psi_nf, + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, phantom: std::marker::PhantomData, }; check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); @@ -1351,28 +1366,30 @@ mod tests { // The proof should fail if !split_flag { let circuit_wrong_psi_nf = OrchardCircuitZSA { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: circuit.cm_old.clone(), - psi_nf: Value::known(pallas::Base::random(&mut rng)), - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: circuit.witnesses.cm_old.clone(), + psi_nf: Value::known(pallas::Base::random(&mut rng)), + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, phantom: std::marker::PhantomData, }; check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false);