From 501c4a75e9a4b1b471dd1a2eb2cc18382f58d865 Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Tue, 19 Sep 2023 22:25:21 +0800 Subject: [PATCH 1/4] improve NoteCommitment --- taiga_halo2/src/action.rs | 14 +++++----- taiga_halo2/src/circuit/merkle_circuit.rs | 4 +-- taiga_halo2/src/circuit/vp_circuit.rs | 13 ++++----- taiga_halo2/src/executable.rs | 7 +++-- taiga_halo2/src/merkle_tree.rs | 32 ++++++++++++++--------- taiga_halo2/src/note.rs | 6 +++++ taiga_halo2/src/shielded_ptx.rs | 8 +++--- taiga_halo2/src/transaction.rs | 13 ++++----- taiga_halo2/src/transparent_ptx.rs | 4 +-- 9 files changed, 59 insertions(+), 42 deletions(-) diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/action.rs index f39b413e..772bed54 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/action.rs @@ -2,7 +2,7 @@ use crate::{ circuit::action_circuit::ActionCircuit, constant::{PRF_EXPAND_INPUT_VP_CM_R, PRF_EXPAND_OUTPUT_VP_CM_R}, merkle_tree::{MerklePath, Node}, - note::{InputNoteProvingInfo, Note, OutputNoteProvingInfo, RandomSeed}, + note::{InputNoteProvingInfo, Note, NoteCommitment, OutputNoteProvingInfo, RandomSeed}, nullifier::Nullifier, value_commitment::ValueCommitment, vp_commitment::ValidityPredicateCommitment, @@ -30,7 +30,7 @@ pub struct ActionInstance { /// The nullifier of input note. pub nf: Nullifier, /// The commitment to the output note. - pub cm: pallas::Base, + pub cm: NoteCommitment, /// net value commitment pub cv_net: ValueCommitment, /// The commitment to input note application(static) vp @@ -56,7 +56,7 @@ impl ActionInstance { vec![ self.nf.inner(), self.anchor, - self.cm, + self.cm.inner(), self.cv_net.get_x(), self.cv_net.get_y(), input_vp_commitment[0], @@ -73,7 +73,7 @@ impl BorshSerialize for ActionInstance { use ff::PrimeField; writer.write_all(&self.anchor.to_repr())?; writer.write_all(&self.nf.to_bytes())?; - writer.write_all(&self.cm.to_repr())?; + writer.write_all(&self.cm.to_bytes())?; writer.write_all(&self.cv_net.to_bytes())?; writer.write_all(&self.input_vp_commitment.to_bytes())?; writer.write_all(&self.output_vp_commitment.to_bytes())?; @@ -93,7 +93,7 @@ impl BorshDeserialize for ActionInstance { let nf = Option::from(Nullifier::from_bytes(nf_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "nf not in field"))?; let cm_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let cm = Option::from(pallas::Base::from_repr(cm_bytes)) + let cm = Option::from(NoteCommitment::from_bytes(cm_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "cm not in field"))?; let cv_net_bytes = <[u8; 32]>::deserialize_reader(reader)?; let cv_net = Option::from(ValueCommitment::from_bytes(cv_net_bytes)) @@ -167,9 +167,9 @@ impl ActionInfo { "The nf of input note should be equal to the rho of output note" ); - let cm = self.output_note.commitment().inner(); + let cm = self.output_note.commitment(); let anchor = { - let cm_node = Node::from_note(&self.input_note); + let cm_node = Node::from(&self.input_note); self.input_merkle_path.root(cm_node).inner() }; diff --git a/taiga_halo2/src/circuit/merkle_circuit.rs b/taiga_halo2/src/circuit/merkle_circuit.rs index fb32cf62..037d45b0 100644 --- a/taiga_halo2/src/circuit/merkle_circuit.rs +++ b/taiga_halo2/src/circuit/merkle_circuit.rs @@ -188,11 +188,11 @@ fn test_halo2_merkle_circuit() { )?; let expected_root = { - let root = self.merkle_path.root(Node::new(self.leaf)).inner(); + let root = self.merkle_path.root(Node::from(self.leaf)); assign_free_advice( layouter.namespace(|| "witness leaf"), config.advices[0], - Value::known(root), + Value::known(root.inner()), )? }; layouter.assign_region( diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index 7a3af678..c53a4cc4 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -1,4 +1,3 @@ -use crate::circuit::vamp_ir_utils::{get_circuit_assignments, parse, VariableAssignmentError}; use crate::{ circuit::{ blake2s::publicize_default_dynamic_vp_commitments, @@ -14,6 +13,7 @@ use crate::{ target_note_variable::{GetIsInputNoteFlagConfig, GetOwnedNoteVariableConfig}, }, integrity::{check_input_note, check_output_note}, + vamp_ir_utils::{get_circuit_assignments, parse, VariableAssignmentError}, }, constant::{ TaigaFixedBases, NOTE_ENCRYPTION_CIPHERTEXT_NUM, NUM_NOTE, SETUP_PARAMS_MAP, @@ -24,14 +24,13 @@ use crate::{ VP_CIRCUIT_OWNED_NOTE_PUB_ID_PUBLIC_INPUT_IDX, VP_CIRCUIT_PARAMS_SIZE, VP_CIRCUIT_PUBLIC_INPUT_NUM, }, - note::{Note, RandomSeed}, + note::{Note, NoteCommitment, RandomSeed}, note_encryption::{NoteCiphertext, SecretKey}, proof::Proof, utils::mod_r_p, vp_vk::ValidityPredicateVerifyingKey, }; use dyn_clone::{clone_trait_object, DynClone}; -//use ff::PrimeField; use group::cofactor::CofactorCurveAffine; use halo2_gadgets::{ ecc::chip::EccChip, @@ -165,12 +164,14 @@ impl VPVerifyingInfo { ] } - pub fn get_note_commitments(&self) -> [pallas::Base; NUM_NOTE] { + pub fn get_note_commitments(&self) -> [NoteCommitment; NUM_NOTE] { [ self.public_inputs - .get_from_index(VP_CIRCUIT_OUTPUT_CM_ONE_PUBLIC_INPUT_IDX), + .get_from_index(VP_CIRCUIT_OUTPUT_CM_ONE_PUBLIC_INPUT_IDX) + .into(), self.public_inputs - .get_from_index(VP_CIRCUIT_OUTPUT_CM_TWO_PUBLIC_INPUT_IDX), + .get_from_index(VP_CIRCUIT_OUTPUT_CM_TWO_PUBLIC_INPUT_IDX) + .into(), ] } diff --git a/taiga_halo2/src/executable.rs b/taiga_halo2/src/executable.rs index 3f3ec0fb..c8dadb0a 100644 --- a/taiga_halo2/src/executable.rs +++ b/taiga_halo2/src/executable.rs @@ -1,11 +1,14 @@ -use crate::{error::TransactionError, nullifier::Nullifier, value_commitment::ValueCommitment}; +use crate::{ + error::TransactionError, note::NoteCommitment, nullifier::Nullifier, + value_commitment::ValueCommitment, +}; use pasta_curves::pallas; // Executable is an unified interface for partial transaction, which is the atomic executable uinit. pub trait Executable { fn execute(&self) -> Result<(), TransactionError>; fn get_nullifiers(&self) -> Vec; - fn get_output_cms(&self) -> Vec; + fn get_output_cms(&self) -> Vec; fn get_value_commitments(&self) -> Vec; fn get_anchors(&self) -> Vec; } diff --git a/taiga_halo2/src/merkle_tree.rs b/taiga_halo2/src/merkle_tree.rs index ab1ea786..26cbce17 100644 --- a/taiga_halo2/src/merkle_tree.rs +++ b/taiga_halo2/src/merkle_tree.rs @@ -93,7 +93,7 @@ impl MerklePath { impl Default for MerklePath { fn default() -> MerklePath { let merkle_path = (0..TAIGA_COMMITMENT_TREE_DEPTH) - .map(|_| (Node::new(pallas::Base::one()), L)) + .map(|_| (Node::from(pallas::Base::one()), L)) .collect(); Self::from_path(merkle_path) } @@ -105,18 +105,6 @@ impl Default for MerklePath { pub struct Node(pallas::Base); impl Node { - pub fn new(v: pallas::Base) -> Self { - Self(v) - } - - pub fn from_note(n: &Note) -> Self { - Self(n.commitment().inner()) - } - - pub fn from_note_commitment(n: &NoteCommitment) -> Self { - Self(n.inner()) - } - pub fn rand(rng: &mut impl RngCore) -> Self { Self(pallas::Base::random(rng)) } @@ -130,6 +118,24 @@ impl Node { } } +impl From for Node { + fn from(node: pallas::Base) -> Node { + Node(node) + } +} + +impl From<&Note> for Node { + fn from(note: &Note) -> Node { + Node(note.commitment().inner()) + } +} + +impl From for Node { + fn from(cm: NoteCommitment) -> Node { + Node(cm.inner()) + } +} + #[cfg(feature = "borsh")] impl BorshSerialize for Node { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { diff --git a/taiga_halo2/src/note.rs b/taiga_halo2/src/note.rs index ecb2337a..d45bd259 100644 --- a/taiga_halo2/src/note.rs +++ b/taiga_halo2/src/note.rs @@ -48,6 +48,12 @@ impl NoteCommitment { } } +impl From for NoteCommitment { + fn from(cm: pallas::Base) -> Self { + NoteCommitment(cm) + } +} + #[cfg(feature = "borsh")] impl BorshSerialize for NoteCommitment { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index c33e43ec..52cd450c 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -6,7 +6,7 @@ use crate::constant::{ }; use crate::error::TransactionError; use crate::executable::Executable; -use crate::note::{InputNoteProvingInfo, OutputNoteProvingInfo}; +use crate::note::{InputNoteProvingInfo, NoteCommitment, OutputNoteProvingInfo}; use crate::nullifier::Nullifier; use crate::proof::Proof; use crate::value_commitment::ValueCommitment; @@ -184,7 +184,7 @@ impl ShieldedPartialTransaction { } // Check the owned_note_id that vp uses is consistent with the cm from the action circuit - if owned_note_id != *action_cm { + if owned_note_id != action_cm.inner() { return Err(TransactionError::InconsistentOwnedNotePubID); } } @@ -229,7 +229,7 @@ impl Executable for ShieldedPartialTransaction { .collect() } - fn get_output_cms(&self) -> Vec { + fn get_output_cms(&self) -> Vec { self.actions .iter() .map(|action| action.action_instance.cm) @@ -388,7 +388,7 @@ impl NoteVPVerifyingInfoSet { nfs } - pub fn get_note_commitments(&self) -> Vec<[pallas::Base; NUM_NOTE]> { + pub fn get_note_commitments(&self) -> Vec<[NoteCommitment; NUM_NOTE]> { let mut cms = vec![self.app_vp_verifying_info.get_note_commitments()]; self.app_dynamic_vp_verifying_info .iter() diff --git a/taiga_halo2/src/transaction.rs b/taiga_halo2/src/transaction.rs index 283115cb..60d25cc2 100644 --- a/taiga_halo2/src/transaction.rs +++ b/taiga_halo2/src/transaction.rs @@ -2,6 +2,7 @@ use crate::binding_signature::{BindingSignature, BindingSigningKey, BindingVerif use crate::constant::TRANSACTION_BINDING_HASH_PERSONALIZATION; use crate::error::TransactionError; use crate::executable::Executable; +use crate::note::NoteCommitment; use crate::nullifier::Nullifier; use crate::shielded_ptx::ShieldedPartialTransaction; use crate::transparent_ptx::{OutputResource, TransparentPartialTransaction}; @@ -56,7 +57,7 @@ pub struct ShieldedPartialTxBundle { pub struct ShieldedResult { pub anchors: Vec, pub nullifiers: Vec, - pub output_cms: Vec, + pub output_cms: Vec, } #[derive(Debug, Clone)] @@ -187,8 +188,8 @@ impl Transaction { bundle.get_nullifiers().iter().for_each(|nf| { h.update(&nf.to_bytes()); }); - bundle.get_output_cms().iter().for_each(|cm_x| { - h.update(&cm_x.to_repr()); + bundle.get_output_cms().iter().for_each(|cm| { + h.update(&cm.to_bytes()); }); bundle.get_value_commitments().iter().for_each(|vc| { h.update(&vc.to_bytes()); @@ -204,7 +205,7 @@ impl Transaction { h.update(&nf.to_bytes()); }); bundle.get_output_cms().iter().for_each(|cm| { - h.update(&cm.to_repr()); + h.update(&cm.to_bytes()); }); bundle.get_value_commitments().iter().for_each(|vc| { h.update(&vc.to_bytes()); @@ -305,7 +306,7 @@ impl ShieldedPartialTxBundle { .collect() } - pub fn get_output_cms(&self) -> Vec { + pub fn get_output_cms(&self) -> Vec { self.partial_txs .iter() .flat_map(|ptx| ptx.get_output_cms()) @@ -366,7 +367,7 @@ impl TransparentPartialTxBundle { .collect() } - pub fn get_output_cms(&self) -> Vec { + pub fn get_output_cms(&self) -> Vec { self.partial_txs .iter() .flat_map(|ptx| ptx.get_output_cms()) diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index 0a6a88a2..ec8a1722 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -1,5 +1,5 @@ use crate::{ - error::TransactionError, executable::Executable, nullifier::Nullifier, + error::TransactionError, executable::Executable, note::NoteCommitment, nullifier::Nullifier, value_commitment::ValueCommitment, }; use pasta_curves::pallas; @@ -28,7 +28,7 @@ impl Executable for TransparentPartialTransaction { unimplemented!() } - fn get_output_cms(&self) -> Vec { + fn get_output_cms(&self) -> Vec { unimplemented!() } From 774cf269d2e5386de0000cfab90008e0a8e3eb80 Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Tue, 19 Sep 2023 22:35:41 +0800 Subject: [PATCH 2/4] improve Nullifier --- taiga_halo2/benches/action_proof.rs | 2 +- taiga_halo2/benches/vp_proof.rs | 2 +- taiga_halo2/deprecated/simple_sudoku/vp.rs | 2 +- taiga_halo2/deprecated/taiga_sudoku/app_vp.rs | 2 +- .../tx_examples/cascaded_partial_transactions.rs | 2 +- .../partial_fulfillment_token_swap.rs | 2 +- taiga_halo2/examples/tx_examples/token.rs | 2 +- .../tx_examples/token_swap_with_intent.rs | 2 +- .../src/circuit/vp_examples/cascade_intent.rs | 2 +- .../circuit/vp_examples/or_relation_intent.rs | 2 +- .../vp_examples/partial_fulfillment_intent.rs | 2 +- taiga_halo2/src/note.rs | 2 +- taiga_halo2/src/nullifier.rs | 16 ++++++++-------- taiga_halo2/src/shielded_ptx.rs | 4 ++-- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/taiga_halo2/benches/action_proof.rs b/taiga_halo2/benches/action_proof.rs index 28a6fe7b..deba38ee 100644 --- a/taiga_halo2/benches/action_proof.rs +++ b/taiga_halo2/benches/action_proof.rs @@ -22,7 +22,7 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { let mut rng = OsRng; let action_info = { let input_note = { - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); let note_type = { let app_vk = pallas::Base::random(&mut rng); diff --git a/taiga_halo2/benches/vp_proof.rs b/taiga_halo2/benches/vp_proof.rs index 61de2863..4916634a 100644 --- a/taiga_halo2/benches/vp_proof.rs +++ b/taiga_halo2/benches/vp_proof.rs @@ -18,7 +18,7 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { let vp_circuit = { let input_notes = [(); NUM_NOTE].map(|_| { - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); let note_type = { let app_vk = pallas::Base::random(&mut rng); diff --git a/taiga_halo2/deprecated/simple_sudoku/vp.rs b/taiga_halo2/deprecated/simple_sudoku/vp.rs index 90a318af..2140a8ca 100644 --- a/taiga_halo2/deprecated/simple_sudoku/vp.rs +++ b/taiga_halo2/deprecated/simple_sudoku/vp.rs @@ -139,7 +139,7 @@ mod tests { let value: u64 = 0; let nk = NullifierKeyContainer::random_key(&mut rng); let rseed = RandomSeed::random(&mut rng); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); Note::new( vp_vk, app_data_static, diff --git a/taiga_halo2/deprecated/taiga_sudoku/app_vp.rs b/taiga_halo2/deprecated/taiga_sudoku/app_vp.rs index 6676020b..e8d12fb4 100644 --- a/taiga_halo2/deprecated/taiga_sudoku/app_vp.rs +++ b/taiga_halo2/deprecated/taiga_sudoku/app_vp.rs @@ -602,7 +602,7 @@ pub mod tests { }; pub fn random_input_note(mut rng: R) -> Note { - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); let note_type = { let app_vk = pallas::Base::random(&mut rng); diff --git a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs index 99141997..e5651b1d 100644 --- a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs +++ b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs @@ -30,7 +30,7 @@ pub fn create_transaction(mut rng: R) -> Transaction { let bob_auth = TokenAuthorization::random(&mut rng); let bob_nk_com = NullifierKeyContainer::random_commitment(&mut rng); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let input_note_1 = create_random_token_note(&mut rng, "btc", 1u64, rho, alice_nk, &alice_auth); let output_note_1 = create_random_token_note( &mut rng, diff --git a/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs b/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs index 774b3ddc..591ae7ca 100644 --- a/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs +++ b/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs @@ -44,7 +44,7 @@ pub fn create_token_intent_ptx( let input_auth = TokenAuthorization::from_sk_vk(&input_auth_sk, &COMPRESSED_TOKEN_AUTH_VK); // input note - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let input_note = create_random_token_note(&mut rng, &sell.name, sell.value, rho, input_nk, &input_auth); diff --git a/taiga_halo2/examples/tx_examples/token.rs b/taiga_halo2/examples/tx_examples/token.rs index 0aecb384..c4735257 100644 --- a/taiga_halo2/examples/tx_examples/token.rs +++ b/taiga_halo2/examples/tx_examples/token.rs @@ -56,7 +56,7 @@ pub fn create_token_swap_ptx( let input_auth = TokenAuthorization::from_sk_vk(&input_auth_sk, &COMPRESSED_TOKEN_AUTH_VK); // input note - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let input_note = create_random_token_note( &mut rng, input_token, diff --git a/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs b/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs index 3ceb7335..2ba87d4b 100644 --- a/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs +++ b/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs @@ -46,7 +46,7 @@ pub fn create_token_intent_ptx( let input_auth = TokenAuthorization::from_sk_vk(&input_auth_sk, &COMPRESSED_TOKEN_AUTH_VK); // input note - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let input_note = create_random_token_note( &mut rng, input_token, diff --git a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs index 27eaece1..9eb45a46 100644 --- a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs @@ -179,7 +179,7 @@ fn test_halo2_cascade_intent_vp_circuit() { let circuit = { let cascade_input_note = random_input_note(&mut rng); let cascade_note_cm = cascade_input_note.commitment().inner(); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::random_key(&mut rng); let intent_note = create_intent_note(&mut rng, cascade_note_cm, rho, nk); let input_notes = [intent_note, cascade_input_note]; diff --git a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs index f4168231..495ee56c 100644 --- a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs @@ -342,7 +342,7 @@ fn test_halo2_or_relation_intent_vp_circuit() { transfrom_token_name_to_token_property(&condition1.token_name); output_notes[0].value = condition1.token_value; - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::random_key(&mut rng); let nk_com = output_notes[0].get_nk_commitment(); let intent_note = create_intent_note( diff --git a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs index df485021..9b37a53c 100644 --- a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs @@ -504,7 +504,7 @@ fn test_halo2_partial_fulfillment_intent_vp_circuit() { sold_note.note_type.app_data_static = transfrom_token_name_to_token_property(&sell.name); sold_note.value = sell.value; let receiver_nk_com = sold_note.get_nk_commitment(); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::random_key(&mut rng); let intent_note = create_intent_note( &mut rng, diff --git a/taiga_halo2/src/note.rs b/taiga_halo2/src/note.rs index d45bd259..83caf9d9 100644 --- a/taiga_halo2/src/note.rs +++ b/taiga_halo2/src/note.rs @@ -192,7 +192,7 @@ impl Note { let app_data_static = pallas::Base::random(&mut rng); let note_type = NoteType::new(app_vk, app_data_static); let app_data_dynamic = pallas::Base::random(&mut rng); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); let rseed = RandomSeed::random(&mut rng); Note { diff --git a/taiga_halo2/src/nullifier.rs b/taiga_halo2/src/nullifier.rs index 4ff50f2b..7bc33cb4 100644 --- a/taiga_halo2/src/nullifier.rs +++ b/taiga_halo2/src/nullifier.rs @@ -35,13 +35,7 @@ pub enum NullifierKeyContainer { } impl Nullifier { - // for test - pub fn new(nf: pallas::Base) -> Self { - Self(nf) - } - - // cm is a field element - // nf = poseidon_hash(nk || \rho || \psi || note_cm) + // nf = poseidon_hash(nk || \rho || \psi || note_cm), in which note_cm is a field element pub fn derive( nk: &NullifierKeyContainer, rho: &pallas::Base, @@ -70,6 +64,12 @@ impl Nullifier { } } +impl From for Nullifier { + fn from(cm: pallas::Base) -> Self { + Nullifier(cm) + } +} + impl Default for Nullifier { fn default() -> Nullifier { Nullifier(pallas::Base::one()) @@ -164,7 +164,7 @@ pub mod tests { use super::{Nullifier, NullifierKeyContainer}; pub fn random_nullifier(mut rng: R) -> Nullifier { - Nullifier::new(pallas::Base::random(&mut rng)) + Nullifier::from(pallas::Base::random(&mut rng)) } pub fn random_nullifier_key(mut rng: R) -> NullifierKeyContainer { diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 52cd450c..5f53ffc9 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -430,7 +430,7 @@ pub mod testing { // The encoding method is flexible and defined in the application vp. // Use poseidon hash to encode the two dynamic VPs here let app_data_dynamic = poseidon_hash(app_dynamic_vp_vk[0], app_dynamic_vp_vk[1]); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let value = 5000u64; let nk = NullifierKeyContainer::random_key(&mut rng); let rseed = RandomSeed::random(&mut rng); @@ -471,7 +471,7 @@ pub mod testing { let input_note_2 = { let app_data_static = pallas::Base::one(); let app_data_dynamic = pallas::Base::zero(); - let rho = Nullifier::new(pallas::Base::random(&mut rng)); + let rho = Nullifier::from(pallas::Base::random(&mut rng)); let value = 10u64; let nk = NullifierKeyContainer::random_key(&mut rng); let rseed = RandomSeed::random(&mut rng); From f200d0a77edf6c6424a0a1f4dd7fbe3d77645afb Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Tue, 19 Sep 2023 22:58:26 +0800 Subject: [PATCH 3/4] add Anchor struct --- taiga_halo2/src/action.rs | 14 +++++------ taiga_halo2/src/executable.rs | 5 ++-- taiga_halo2/src/merkle_tree.rs | 39 ++++++++++++++++++++++++++++-- taiga_halo2/src/shielded_ptx.rs | 3 ++- taiga_halo2/src/transaction.rs | 16 ++++++------ taiga_halo2/src/transparent_ptx.rs | 7 +++--- 6 files changed, 57 insertions(+), 27 deletions(-) diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/action.rs index 772bed54..3e0eaa92 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/action.rs @@ -1,7 +1,7 @@ use crate::{ circuit::action_circuit::ActionCircuit, constant::{PRF_EXPAND_INPUT_VP_CM_R, PRF_EXPAND_OUTPUT_VP_CM_R}, - merkle_tree::{MerklePath, Node}, + merkle_tree::{Anchor, MerklePath, Node}, note::{InputNoteProvingInfo, Note, NoteCommitment, OutputNoteProvingInfo, RandomSeed}, nullifier::Nullifier, value_commitment::ValueCommitment, @@ -26,7 +26,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ActionInstance { /// The root of the note commitment Merkle tree. - pub anchor: pallas::Base, + pub anchor: Anchor, /// The nullifier of input note. pub nf: Nullifier, /// The commitment to the output note. @@ -55,7 +55,7 @@ impl ActionInstance { let output_vp_commitment = self.output_vp_commitment.to_public_inputs(); vec![ self.nf.inner(), - self.anchor, + self.anchor.inner(), self.cm.inner(), self.cv_net.get_x(), self.cv_net.get_y(), @@ -70,8 +70,7 @@ impl ActionInstance { #[cfg(feature = "borsh")] impl BorshSerialize for ActionInstance { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - use ff::PrimeField; - writer.write_all(&self.anchor.to_repr())?; + writer.write_all(&self.anchor.to_bytes())?; writer.write_all(&self.nf.to_bytes())?; writer.write_all(&self.cm.to_bytes())?; writer.write_all(&self.cv_net.to_bytes())?; @@ -84,10 +83,9 @@ impl BorshSerialize for ActionInstance { #[cfg(feature = "borsh")] impl BorshDeserialize for ActionInstance { fn deserialize_reader(reader: &mut R) -> std::io::Result { - use ff::PrimeField; use std::io; let anchor_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let anchor = Option::from(pallas::Base::from_repr(anchor_bytes)) + let anchor = Option::from(Anchor::from_bytes(anchor_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "anchor not in field"))?; let nf_bytes = <[u8; 32]>::deserialize_reader(reader)?; let nf = Option::from(Nullifier::from_bytes(nf_bytes)) @@ -170,7 +168,7 @@ impl ActionInfo { let cm = self.output_note.commitment(); let anchor = { let cm_node = Node::from(&self.input_note); - self.input_merkle_path.root(cm_node).inner() + self.input_merkle_path.root(cm_node) }; let rcv = self.get_rcv(); diff --git a/taiga_halo2/src/executable.rs b/taiga_halo2/src/executable.rs index c8dadb0a..c7fc3475 100644 --- a/taiga_halo2/src/executable.rs +++ b/taiga_halo2/src/executable.rs @@ -1,8 +1,7 @@ use crate::{ - error::TransactionError, note::NoteCommitment, nullifier::Nullifier, + error::TransactionError, merkle_tree::Anchor, note::NoteCommitment, nullifier::Nullifier, value_commitment::ValueCommitment, }; -use pasta_curves::pallas; // Executable is an unified interface for partial transaction, which is the atomic executable uinit. pub trait Executable { @@ -10,5 +9,5 @@ pub trait Executable { fn get_nullifiers(&self) -> Vec; fn get_output_cms(&self) -> Vec; fn get_value_commitments(&self) -> Vec; - fn get_anchors(&self) -> Vec; + fn get_anchors(&self) -> Vec; } diff --git a/taiga_halo2/src/merkle_tree.rs b/taiga_halo2/src/merkle_tree.rs index 26cbce17..700872bb 100644 --- a/taiga_halo2/src/merkle_tree.rs +++ b/taiga_halo2/src/merkle_tree.rs @@ -9,6 +9,9 @@ use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; use rand::distributions::{Distribution, Standard}; use rand::{Rng, RngCore}; +#[cfg(feature = "nif")] +use rustler::NifTuple; +use subtle::CtOption; #[cfg(feature = "serde")] use serde; @@ -16,6 +19,38 @@ use serde; #[cfg(feature = "borsh")] use borsh::{BorshDeserialize, BorshSerialize}; +/// The root of the note commitment Merkletree. +#[derive(Eq, PartialEq, Clone, Copy, Debug)] +#[cfg_attr(feature = "nif", derive(NifTuple))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Anchor(pallas::Base); + +impl Anchor { + pub fn inner(&self) -> pallas::Base { + self.0 + } + + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_repr() + } + + pub fn from_bytes(bytes: [u8; 32]) -> CtOption { + pallas::Base::from_repr(bytes).map(Anchor) + } +} + +impl From for Anchor { + fn from(anchor: pallas::Base) -> Anchor { + Anchor(anchor) + } +} + +impl From for Anchor { + fn from(node: Node) -> Anchor { + Anchor(node.0) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default)] #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -70,7 +105,7 @@ impl MerklePath { } /// Returns the root of the tree corresponding to this path applied to `leaf`. - pub fn root(&self, leaf: Node) -> Node { + pub fn root(&self, leaf: Node) -> Anchor { let mut root = leaf; for val in self.merkle_path.iter() { root = match val.1 { @@ -78,7 +113,7 @@ impl MerklePath { L => Node::combine(&val.0, &root), } } - root + root.into() } /// Returns the input parameters for merkle tree gadget. diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 5f53ffc9..ef33f549 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -6,6 +6,7 @@ use crate::constant::{ }; use crate::error::TransactionError; use crate::executable::Executable; +use crate::merkle_tree::Anchor; use crate::note::{InputNoteProvingInfo, NoteCommitment, OutputNoteProvingInfo}; use crate::nullifier::Nullifier; use crate::proof::Proof; @@ -243,7 +244,7 @@ impl Executable for ShieldedPartialTransaction { .collect() } - fn get_anchors(&self) -> Vec { + fn get_anchors(&self) -> Vec { self.actions .iter() .map(|action| action.action_instance.anchor) diff --git a/taiga_halo2/src/transaction.rs b/taiga_halo2/src/transaction.rs index 60d25cc2..3a3a69cf 100644 --- a/taiga_halo2/src/transaction.rs +++ b/taiga_halo2/src/transaction.rs @@ -2,16 +2,14 @@ use crate::binding_signature::{BindingSignature, BindingSigningKey, BindingVerif use crate::constant::TRANSACTION_BINDING_HASH_PERSONALIZATION; use crate::error::TransactionError; use crate::executable::Executable; +use crate::merkle_tree::Anchor; use crate::note::NoteCommitment; use crate::nullifier::Nullifier; use crate::shielded_ptx::ShieldedPartialTransaction; use crate::transparent_ptx::{OutputResource, TransparentPartialTransaction}; use crate::value_commitment::ValueCommitment; use blake2b_simd::Params as Blake2bParams; -use pasta_curves::{ - group::{ff::PrimeField, Group}, - pallas, -}; +use pasta_curves::{group::Group, pallas}; use rand::{CryptoRng, RngCore}; #[cfg(feature = "nif")] @@ -55,7 +53,7 @@ pub struct ShieldedPartialTxBundle { #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Transaction.Result")] pub struct ShieldedResult { - pub anchors: Vec, + pub anchors: Vec, pub nullifiers: Vec, pub output_cms: Vec, } @@ -195,7 +193,7 @@ impl Transaction { h.update(&vc.to_bytes()); }); bundle.get_anchors().iter().for_each(|anchor| { - h.update(&anchor.to_repr()); + h.update(&anchor.to_bytes()); }); } @@ -211,7 +209,7 @@ impl Transaction { h.update(&vc.to_bytes()); }); bundle.get_anchors().iter().for_each(|anchor| { - h.update(&anchor.to_repr()); + h.update(&anchor.to_bytes()); }); } @@ -313,7 +311,7 @@ impl ShieldedPartialTxBundle { .collect() } - pub fn get_anchors(&self) -> Vec { + pub fn get_anchors(&self) -> Vec { self.partial_txs .iter() .flat_map(|ptx| ptx.get_anchors()) @@ -374,7 +372,7 @@ impl TransparentPartialTxBundle { .collect() } - pub fn get_anchors(&self) -> Vec { + pub fn get_anchors(&self) -> Vec { self.partial_txs .iter() .flat_map(|ptx| ptx.get_anchors()) diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index ec8a1722..77308aa1 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -1,8 +1,7 @@ use crate::{ - error::TransactionError, executable::Executable, note::NoteCommitment, nullifier::Nullifier, - value_commitment::ValueCommitment, + error::TransactionError, executable::Executable, merkle_tree::Anchor, note::NoteCommitment, + nullifier::Nullifier, value_commitment::ValueCommitment, }; -use pasta_curves::pallas; #[cfg(feature = "serde")] use serde; @@ -36,7 +35,7 @@ impl Executable for TransparentPartialTransaction { unimplemented!() } - fn get_anchors(&self) -> Vec { + fn get_anchors(&self) -> Vec { unimplemented!() } } From dbb8e84fc2b2c03b57c0c2ccd485b27a8d2e2dda Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Tue, 19 Sep 2023 23:00:12 +0800 Subject: [PATCH 4/4] rename ActionInstance to ActionPublicInputs --- taiga_halo2/src/action.rs | 20 ++++++++++---------- taiga_halo2/src/shielded_ptx.rs | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/action.rs index 3e0eaa92..7317efc1 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/action.rs @@ -19,12 +19,12 @@ use serde; #[cfg(feature = "borsh")] use borsh::{BorshDeserialize, BorshSerialize}; -/// The action result used in transaction. +/// The public inputs of action proof. #[derive(Debug, Clone)] #[cfg_attr(feature = "nif", derive(NifStruct))] -#[cfg_attr(feature = "nif", module = "Taiga.Action.Instance")] +#[cfg_attr(feature = "nif", module = "Taiga.Action.PublicInputs")] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ActionInstance { +pub struct ActionPublicInputs { /// The root of the note commitment Merkle tree. pub anchor: Anchor, /// The nullifier of input note. @@ -39,7 +39,7 @@ pub struct ActionInstance { pub output_vp_commitment: ValidityPredicateCommitment, } -/// The information to build ActionInstance and ActionCircuit. +/// The information to build ActionPublicInputs and ActionCircuit. #[derive(Clone)] pub struct ActionInfo { input_note: Note, @@ -49,7 +49,7 @@ pub struct ActionInfo { rseed: RandomSeed, } -impl ActionInstance { +impl ActionPublicInputs { pub fn to_instance(&self) -> Vec { let input_vp_commitment = self.input_vp_commitment.to_public_inputs(); let output_vp_commitment = self.output_vp_commitment.to_public_inputs(); @@ -68,7 +68,7 @@ impl ActionInstance { } #[cfg(feature = "borsh")] -impl BorshSerialize for ActionInstance { +impl BorshSerialize for ActionPublicInputs { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.anchor.to_bytes())?; writer.write_all(&self.nf.to_bytes())?; @@ -81,7 +81,7 @@ impl BorshSerialize for ActionInstance { } #[cfg(feature = "borsh")] -impl BorshDeserialize for ActionInstance { +impl BorshDeserialize for ActionPublicInputs { fn deserialize_reader(reader: &mut R) -> std::io::Result { use std::io; let anchor_bytes = <[u8; 32]>::deserialize_reader(reader)?; @@ -103,7 +103,7 @@ impl BorshDeserialize for ActionInstance { let output_vp_commitment = ValidityPredicateCommitment::from_bytes(output_vp_commitment_bytes); - Ok(ActionInstance { + Ok(ActionPublicInputs { anchor, nf, cm, @@ -158,7 +158,7 @@ impl ActionInfo { self.rseed.get_vp_cm_r(PRF_EXPAND_OUTPUT_VP_CM_R) } - pub fn build(&self) -> (ActionInstance, ActionCircuit) { + pub fn build(&self) -> (ActionPublicInputs, ActionCircuit) { let nf = self.input_note.get_nf().unwrap(); assert_eq!( nf, self.output_note.rho, @@ -182,7 +182,7 @@ impl ActionInfo { let output_vp_commitment = ValidityPredicateCommitment::commit(&self.output_note.get_app_vk(), &output_vp_cm_r); - let action = ActionInstance { + let action = ActionPublicInputs { nf, cm, anchor, diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index ef33f549..7ead140f 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -1,4 +1,4 @@ -use crate::action::{ActionInfo, ActionInstance}; +use crate::action::{ActionInfo, ActionPublicInputs}; use crate::circuit::vp_circuit::{VPVerifyingInfo, ValidityPredicate}; use crate::constant::{ ACTION_CIRCUIT_PARAMS_SIZE, ACTION_PROVING_KEY, ACTION_VERIFYING_KEY, MAX_DYNAMIC_VP_NUM, @@ -39,7 +39,7 @@ pub struct ShieldedPartialTransaction { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ActionVerifyingInfo { action_proof: Proof, - action_instance: ActionInstance, + action_instance: ActionPublicInputs, } #[derive(Debug, Clone)]