From 656f5f96e45f671e306afff8fec2bf6e635fea5c Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Wed, 29 Nov 2023 18:32:14 +0800 Subject: [PATCH 1/5] rename the action to the compliance --- taiga_halo2/Cargo.toml | 2 +- taiga_halo2/benches/Perfromance.md | 6 +- .../{action_proof.rs => compliance_proof.rs} | 36 +++-- .../cascaded_partial_transactions.rs | 28 ++-- .../partial_fulfillment_token_swap.rs | 29 ++-- taiga_halo2/examples/tx_examples/token.rs | 14 +- .../tx_examples/token_swap_with_intent.rs | 29 ++-- ...ction_circuit.rs => compliance_circuit.rs} | 79 +++++---- taiga_halo2/src/circuit/mod.rs | 2 +- taiga_halo2/src/circuit/vp_bytecode.rs | 24 +-- taiga_halo2/src/{action.rs => compliance.rs} | 42 ++--- taiga_halo2/src/constant.rs | 46 +++--- taiga_halo2/src/error.rs | 12 +- taiga_halo2/src/lib.rs | 2 +- taiga_halo2/src/resource.rs | 4 +- taiga_halo2/src/shielded_ptx.rs | 152 +++++++++--------- taiga_halo2/src/taiga_api.rs | 17 +- taiga_halo2/src/transparent_ptx.rs | 48 +++--- 18 files changed, 301 insertions(+), 271 deletions(-) rename taiga_halo2/benches/{action_proof.rs => compliance_proof.rs} (81%) rename taiga_halo2/src/circuit/{action_circuit.rs => compliance_circuit.rs} (84%) rename taiga_halo2/src/{action.rs => compliance.rs} (86%) diff --git a/taiga_halo2/Cargo.toml b/taiga_halo2/Cargo.toml index 2e0b0bea..857e7b7e 100644 --- a/taiga_halo2/Cargo.toml +++ b/taiga_halo2/Cargo.toml @@ -32,7 +32,7 @@ proptest = "1.2" serde_json = "1.0" [[bench]] -name = "action_proof" +name = "compliance_proof" harness = false [[bench]] diff --git a/taiga_halo2/benches/Perfromance.md b/taiga_halo2/benches/Perfromance.md index ae5a7947..e1cc150c 100644 --- a/taiga_halo2/benches/Perfromance.md +++ b/taiga_halo2/benches/Perfromance.md @@ -1,7 +1,7 @@ -# Action proof performance +# Compliance proof performance ``` -action-proof-prover time: [3.6500 s 3.1445 s 3.7210 s] -action-proof-verifier time: [35.858 ms 36.359 ms 36.873 ms] +compliance-proof-prover time: [3.6500 s 3.1445 s 3.7210 s] +compliance-proof-verifier time: [35.858 ms 36.359 ms 36.873 ms] ``` # VP proof performance diff --git a/taiga_halo2/benches/action_proof.rs b/taiga_halo2/benches/compliance_proof.rs similarity index 81% rename from taiga_halo2/benches/action_proof.rs rename to taiga_halo2/benches/compliance_proof.rs index 1613177c..0df94f7c 100644 --- a/taiga_halo2/benches/action_proof.rs +++ b/taiga_halo2/benches/compliance_proof.rs @@ -8,19 +8,19 @@ use pasta_curves::{pallas, vesta}; use rand::rngs::OsRng; use rand::Rng; use taiga_halo2::{ - action::ActionInfo, + compliance::ComplianceInfo, constant::{ - ACTION_CIRCUIT_PARAMS_SIZE, ACTION_PROVING_KEY, ACTION_VERIFYING_KEY, SETUP_PARAMS_MAP, - TAIGA_COMMITMENT_TREE_DEPTH, + COMPLIANCE_CIRCUIT_PARAMS_SIZE, COMPLIANCE_PROVING_KEY, COMPLIANCE_VERIFYING_KEY, + SETUP_PARAMS_MAP, TAIGA_COMMITMENT_TREE_DEPTH, }, merkle_tree::MerklePath, nullifier::{Nullifier, NullifierKeyContainer}, resource::{RandomSeed, Resource, ResourceKind}, }; -fn bench_action_proof(name: &str, c: &mut Criterion) { +fn bench_compliance_proof(name: &str, c: &mut Criterion) { let mut rng = OsRng; - let action_info = { + let compliance_info = { let input_resource = { let nonce = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); @@ -66,7 +66,7 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { } }; let input_merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - ActionInfo::new( + ComplianceInfo::new( input_resource, input_merkle_path, None, @@ -74,8 +74,10 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { &mut rng, ) }; - let (action, action_circuit) = action_info.build(); - let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); + let (compliance, compliance_circuit) = compliance_info.build(); + let params = SETUP_PARAMS_MAP + .get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE) + .unwrap(); // Prover bench let prover_name = name.to_string() + "-prover"; @@ -84,9 +86,9 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); create_proof( params, - &ACTION_PROVING_KEY, - &[action_circuit.clone()], - &[&[&action.to_instance()]], + &COMPLIANCE_PROVING_KEY, + &[compliance_circuit.clone()], + &[&[&compliance.to_instance()]], &mut rng, &mut transcript, ) @@ -101,9 +103,9 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); create_proof( params, - &ACTION_PROVING_KEY, - &[action_circuit], - &[&[&action.to_instance()]], + &COMPLIANCE_PROVING_KEY, + &[compliance_circuit], + &[&[&compliance.to_instance()]], &mut rng, &mut transcript, ) @@ -118,9 +120,9 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { let mut transcript = Blake2bRead::init(&proof[..]); assert!(verify_proof( params, - &ACTION_VERIFYING_KEY, + &COMPLIANCE_VERIFYING_KEY, strategy, - &[&[&action.to_instance()]], + &[&[&compliance.to_instance()]], &mut transcript ) .is_ok()); @@ -128,7 +130,7 @@ fn bench_action_proof(name: &str, c: &mut Criterion) { }); } fn criterion_benchmark(c: &mut Criterion) { - bench_action_proof("halo2-action-proof", c); + bench_compliance_proof("halo2-compliance-proof", c); } criterion_group!(benches, criterion_benchmark); diff --git a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs index 37140218..f08c0911 100644 --- a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs +++ b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs @@ -5,12 +5,12 @@ use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; use rand::{CryptoRng, RngCore}; use taiga_halo2::{ - action::ActionInfo, circuit::vp_examples::{ cascade_intent::{create_intent_resource, CascadeIntentValidityPredicateCircuit}, signature_verification::COMPRESSED_TOKEN_AUTH_VK, token::{Token, TokenAuthorization}, }, + compliance::ComplianceInfo, constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::{Anchor, MerklePath}, resource::ResourceValidityPredicates, @@ -57,9 +57,9 @@ pub fn create_transaction(mut rng: R) -> Transaction { // Alice consumes 1 "BTC" and 2 "ETH". // Alice creates a cascade intent resource and 1 "BTC" to Bob. let ptx_1 = { - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( *input_resource_1.resource(), merkle_path.clone(), None, @@ -67,14 +67,14 @@ pub fn create_transaction(mut rng: R) -> Transaction { &mut rng, ); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( *input_resource_2.resource(), merkle_path.clone(), None, &mut cascade_intent_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -127,16 +127,17 @@ pub fn create_transaction(mut rng: R) -> Transaction { }; // Create shielded partial tx - ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng).unwrap() + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng) + .unwrap() }; // The second partial transaction: // Alice consumes the intent resource and 3 "XAN"; // Alice creates 2 "ETH" and 3 "XAN" to Bob let ptx_2 = { - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( cascade_intent_resource, merkle_path.clone(), Some(anchor), @@ -144,14 +145,14 @@ pub fn create_transaction(mut rng: R) -> Transaction { &mut rng, ); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( *input_resource_3.resource(), merkle_path, None, &mut output_resource_3.resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -203,7 +204,8 @@ pub fn create_transaction(mut rng: R) -> Transaction { }; // Create shielded partial tx - ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng).unwrap() + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng) + .unwrap() }; // Create the final transaction 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 91a89408..e7f91e23 100644 --- a/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs +++ b/taiga_halo2/examples/tx_examples/partial_fulfillment_token_swap.rs @@ -9,12 +9,12 @@ use halo2_proofs::arithmetic::Field; use pasta_curves::{group::Curve, pallas}; use rand::{CryptoRng, RngCore}; use taiga_halo2::{ - action::ActionInfo, circuit::vp_examples::{ partial_fulfillment_intent::{PartialFulfillmentIntentValidityPredicateCircuit, Swap}, signature_verification::COMPRESSED_TOKEN_AUTH_VK, token::{Token, TokenAuthorization, TokenResource}, }, + compliance::ComplianceInfo, constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::{Anchor, MerklePath}, nullifier::NullifierKeyContainer, @@ -38,9 +38,9 @@ pub fn create_token_intent_ptx( let mut padding_output_resource = Resource::random_padding_resource(&mut rng); let merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( *swap.sell.resource(), merkle_path.clone(), None, @@ -50,14 +50,14 @@ pub fn create_token_intent_ptx( // Fetch a valid anchor for dummy resources let anchor = Anchor::from(pallas::Base::random(&mut rng)); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( padding_input_resource, merkle_path, Some(anchor), &mut padding_output_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -106,8 +106,9 @@ pub fn create_token_intent_ptx( }; // Create shielded partial tx - let ptx = ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng) - .unwrap(); + let ptx = + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng) + .unwrap(); (ptx, swap, intent_resource) } @@ -131,9 +132,9 @@ pub fn consume_token_intent_ptx( // Fetch a valid anchor for dummy resources let anchor = Anchor::from(pallas::Base::random(&mut rng)); - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( intent_resource, merkle_path.clone(), Some(anchor), @@ -141,14 +142,14 @@ pub fn consume_token_intent_ptx( &mut rng, ); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( padding_input_resource, merkle_path, Some(anchor), &mut returned_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -204,7 +205,7 @@ pub fn consume_token_intent_ptx( }; // Create shielded partial tx - ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng).unwrap() + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng).unwrap() } pub fn create_token_swap_transaction(mut rng: R) -> Transaction { diff --git a/taiga_halo2/examples/tx_examples/token.rs b/taiga_halo2/examples/tx_examples/token.rs index 9d9aec9a..1202d27f 100644 --- a/taiga_halo2/examples/tx_examples/token.rs +++ b/taiga_halo2/examples/tx_examples/token.rs @@ -4,11 +4,11 @@ use pasta_curves::pallas; use rand::RngCore; use taiga_halo2::{ - action::ActionInfo, circuit::vp_examples::{ signature_verification::COMPRESSED_TOKEN_AUTH_VK, token::{Token, TokenAuthorization}, }, + compliance::ComplianceInfo, constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::{Anchor, MerklePath}, resource::{Resource, ResourceValidityPredicates}, @@ -43,9 +43,9 @@ pub fn create_token_swap_ptx( // Generate proving info let merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( *input_resource.resource(), merkle_path.clone(), None, @@ -55,14 +55,14 @@ pub fn create_token_swap_ptx( // Fetch a valid anchor for padding input resources let anchor = Anchor::from(pallas::Base::random(&mut rng)); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( padding_input_resource, merkle_path, Some(anchor), &mut padding_output_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -107,5 +107,5 @@ pub fn create_token_swap_ptx( }; // Create shielded partial tx - ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng).unwrap() + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng).unwrap() } 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 3a6928ab..8ee10ef7 100644 --- a/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs +++ b/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs @@ -9,12 +9,12 @@ use halo2_proofs::arithmetic::Field; use pasta_curves::{group::Curve, pallas}; use rand::{CryptoRng, RngCore}; use taiga_halo2::{ - action::ActionInfo, circuit::vp_examples::{ or_relation_intent::{create_intent_resource, OrRelationIntentValidityPredicateCircuit}, signature_verification::COMPRESSED_TOKEN_AUTH_VK, token::{Token, TokenAuthorization}, }, + compliance::ComplianceInfo, constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::{Anchor, MerklePath}, nullifier::NullifierKeyContainer, @@ -59,9 +59,9 @@ pub fn create_token_intent_ptx( let merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( *input_resource.resource(), merkle_path.clone(), None, @@ -71,14 +71,14 @@ pub fn create_token_intent_ptx( // Fetch a valid anchor for padding input resources let anchor = Anchor::from(pallas::Base::random(&mut rng)); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( padding_input_resource, merkle_path, Some(anchor), &mut padding_output_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -130,8 +130,9 @@ pub fn create_token_intent_ptx( }; // Create shielded partial tx - let ptx = ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng) - .unwrap(); + let ptx = + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng) + .unwrap(); (ptx, input_nk, input_resource_npk, input_resource.value) } @@ -173,9 +174,9 @@ pub fn consume_token_intent_ptx( // Fetch a valid anchor for dummy resources let anchor = Anchor::from(pallas::Base::random(&mut rng)); - // Create action pairs - let actions = { - let action_1 = ActionInfo::new( + // Create compliance pairs + let compliances = { + let compliance_1 = ComplianceInfo::new( intent_resource, merkle_path.clone(), Some(anchor), @@ -183,14 +184,14 @@ pub fn consume_token_intent_ptx( &mut rng, ); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( padding_input_resource, merkle_path, Some(anchor), &mut padding_output_resource, &mut rng, ); - vec![action_1, action_2] + vec![compliance_1, compliance_2] }; // Create VPs @@ -241,7 +242,7 @@ pub fn consume_token_intent_ptx( }; // Create shielded partial tx - ShieldedPartialTransaction::build(actions, input_vps, output_vps, vec![], &mut rng).unwrap() + ShieldedPartialTransaction::build(compliances, input_vps, output_vps, vec![], &mut rng).unwrap() } pub fn create_token_swap_intent_transaction(mut rng: R) -> Transaction { diff --git a/taiga_halo2/src/circuit/action_circuit.rs b/taiga_halo2/src/circuit/compliance_circuit.rs similarity index 84% rename from taiga_halo2/src/circuit/action_circuit.rs rename to taiga_halo2/src/circuit/compliance_circuit.rs index 6830c187..2d4b4e41 100644 --- a/taiga_halo2/src/circuit/action_circuit.rs +++ b/taiga_halo2/src/circuit/compliance_circuit.rs @@ -8,11 +8,12 @@ use crate::circuit::merkle_circuit::{ merkle_poseidon_gadget, MerklePoseidonChip, MerklePoseidonConfig, }; use crate::constant::{ - TaigaFixedBases, ACTION_ANCHOR_PUBLIC_INPUT_ROW_IDX, ACTION_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX, - ACTION_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX, ACTION_INPUT_VP_CM_1_ROW_IDX, - ACTION_INPUT_VP_CM_2_ROW_IDX, ACTION_NF_PUBLIC_INPUT_ROW_IDX, - ACTION_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX, ACTION_OUTPUT_VP_CM_1_ROW_IDX, - ACTION_OUTPUT_VP_CM_2_ROW_IDX, TAIGA_COMMITMENT_TREE_DEPTH, + TaigaFixedBases, COMPLIANCE_ANCHOR_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX, COMPLIANCE_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_INPUT_VP_CM_1_ROW_IDX, COMPLIANCE_INPUT_VP_CM_2_ROW_IDX, + COMPLIANCE_NF_PUBLIC_INPUT_ROW_IDX, COMPLIANCE_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_OUTPUT_VP_CM_1_ROW_IDX, COMPLIANCE_OUTPUT_VP_CM_2_ROW_IDX, + TAIGA_COMMITMENT_TREE_DEPTH, }; use crate::merkle_tree::LR; use crate::resource::Resource; @@ -35,7 +36,7 @@ use pasta_curves::pallas; use crate::circuit::resource_commitment::{ResourceCommitChip, ResourceCommitConfig}; #[derive(Clone, Debug)] -pub struct ActionConfig { +pub struct ComplianceConfig { instances: Column, advices: [Column; 10], table_idx: TableColumn, @@ -48,9 +49,9 @@ pub struct ActionConfig { resource_commit_config: ResourceCommitConfig, } -/// The Action circuit. +/// The Compliance circuit. #[derive(Clone, Debug, Default)] -pub struct ActionCircuit { +pub struct ComplianceCircuit { /// Input resource pub input_resource: Resource, /// The authorization path of input resource @@ -65,8 +66,8 @@ pub struct ActionCircuit { pub output_vp_cm_r: pallas::Base, } -impl Circuit for ActionCircuit { - type Config = ActionConfig; +impl Circuit for ComplianceCircuit { + type Config = ComplianceConfig; type FloorPlanner = floor_planner::V1; fn without_witnesses(&self) -> Self { @@ -209,7 +210,7 @@ impl Circuit for ActionCircuit { config.instances, resource_commit_chip.clone(), self.input_resource, - ACTION_NF_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_NF_PUBLIC_INPUT_ROW_IDX, )?; // Check the merkle tree path validity and public the root @@ -228,7 +229,7 @@ impl Circuit for ActionCircuit { resource_commit_chip, self.output_resource, input_resource_variables.nf, - ACTION_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX, )?; // compute and public delta commitment(input_value_commitment - output_value_commitment) @@ -247,12 +248,12 @@ impl Circuit for ActionCircuit { layouter.constrain_instance( delta.inner().x().cell(), config.instances, - ACTION_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX, )?; layouter.constrain_instance( delta.inner().y().cell(), config.instances, - ACTION_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX, )?; // merkle path check @@ -271,7 +272,7 @@ impl Circuit for ActionCircuit { region.assign_advice_from_instance( || "anchor", config.instances, - ACTION_ANCHOR_PUBLIC_INPUT_ROW_IDX, + COMPLIANCE_ANCHOR_PUBLIC_INPUT_ROW_IDX, config.advices[1], 0, )?; @@ -295,12 +296,12 @@ impl Circuit for ActionCircuit { layouter.constrain_instance( input_vp_commitment[0].cell(), config.instances, - ACTION_INPUT_VP_CM_1_ROW_IDX, + COMPLIANCE_INPUT_VP_CM_1_ROW_IDX, )?; layouter.constrain_instance( input_vp_commitment[1].cell(), config.instances, - ACTION_INPUT_VP_CM_2_ROW_IDX, + COMPLIANCE_INPUT_VP_CM_2_ROW_IDX, )?; // Output resource application VP commitment @@ -318,12 +319,12 @@ impl Circuit for ActionCircuit { layouter.constrain_instance( output_vp_commitment[0].cell(), config.instances, - ACTION_OUTPUT_VP_CM_1_ROW_IDX, + COMPLIANCE_OUTPUT_VP_CM_1_ROW_IDX, )?; layouter.constrain_instance( output_vp_commitment[1].cell(), config.instances, - ACTION_OUTPUT_VP_CM_2_ROW_IDX, + COMPLIANCE_OUTPUT_VP_CM_2_ROW_IDX, )?; Ok(()) @@ -331,10 +332,11 @@ impl Circuit for ActionCircuit { } #[test] -fn test_halo2_action_circuit() { - use crate::action::tests::random_action_info; +fn test_halo2_compliance_circuit() { + use crate::compliance::tests::random_compliance_info; use crate::constant::{ - ACTION_CIRCUIT_PARAMS_SIZE, ACTION_PROVING_KEY, ACTION_VERIFYING_KEY, SETUP_PARAMS_MAP, + COMPLIANCE_CIRCUIT_PARAMS_SIZE, COMPLIANCE_PROVING_KEY, COMPLIANCE_VERIFYING_KEY, + SETUP_PARAMS_MAP, }; use crate::proof::Proof; use halo2_proofs::dev::MockProver; @@ -342,26 +344,35 @@ fn test_halo2_action_circuit() { use rand::rngs::OsRng; let mut rng = OsRng; - let action_info = random_action_info(&mut rng); - let (action, action_circuit) = action_info.build(); - let instances = vec![action.to_instance()]; - let prover = - MockProver::::run(ACTION_CIRCUIT_PARAMS_SIZE, &action_circuit, instances) - .unwrap(); + let compliance_info = random_compliance_info(&mut rng); + let (compliance, compliance_circuit) = compliance_info.build(); + let instances = vec![compliance.to_instance()]; + let prover = MockProver::::run( + COMPLIANCE_CIRCUIT_PARAMS_SIZE, + &compliance_circuit, + instances, + ) + .unwrap(); assert_eq!(prover.verify(), Ok(())); - // Create action proof - let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); + // Create compliance proof + let params = SETUP_PARAMS_MAP + .get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE) + .unwrap(); let proof = Proof::create( - &ACTION_PROVING_KEY, + &COMPLIANCE_PROVING_KEY, params, - action_circuit, - &[&action.to_instance()], + compliance_circuit, + &[&compliance.to_instance()], &mut rng, ) .unwrap(); assert!(proof - .verify(&ACTION_VERIFYING_KEY, params, &[&action.to_instance()]) + .verify( + &COMPLIANCE_VERIFYING_KEY, + params, + &[&compliance.to_instance()] + ) .is_ok()); } diff --git a/taiga_halo2/src/circuit/mod.rs b/taiga_halo2/src/circuit/mod.rs index 8ebef428..d6c4cc3a 100644 --- a/taiga_halo2/src/circuit/mod.rs +++ b/taiga_halo2/src/circuit/mod.rs @@ -1,4 +1,4 @@ -pub mod action_circuit; +pub mod compliance_circuit; pub mod gadgets; pub mod integrity; pub mod merkle_circuit; diff --git a/taiga_halo2/src/circuit/vp_bytecode.rs b/taiga_halo2/src/circuit/vp_bytecode.rs index b202d762..202edcf8 100644 --- a/taiga_halo2/src/circuit/vp_bytecode.rs +++ b/taiga_halo2/src/circuit/vp_bytecode.rs @@ -82,8 +82,8 @@ impl ValidityPredicateByteCode { // Verify vp circuit transparently and return owned resource PubID for further checking pub fn verify_transparently( &self, - action_nfs: &[Nullifier], - action_cms: &[ResourceCommitment], + compliance_nfs: &[Nullifier], + compliance_cms: &[ResourceCommitment], ) -> Result { // check VP transparently let public_inputs = match &self.circuit { @@ -109,26 +109,26 @@ impl ValidityPredicateByteCode { }; // check nullifiers - // Check the vp actually uses the input resources from action circuits. + // Check the vp actually uses the input resources from compliance circuits. let vp_nfs = [ public_inputs.get_from_index(VP_CIRCUIT_NULLIFIER_ONE_PUBLIC_INPUT_IDX), public_inputs.get_from_index(VP_CIRCUIT_NULLIFIER_TWO_PUBLIC_INPUT_IDX), ]; - if !((action_nfs[0].inner() == vp_nfs[0] && action_nfs[1].inner() == vp_nfs[1]) - || (action_nfs[0].inner() == vp_nfs[1] && action_nfs[1].inner() == vp_nfs[0])) + if !((compliance_nfs[0].inner() == vp_nfs[0] && compliance_nfs[1].inner() == vp_nfs[1]) + || (compliance_nfs[0].inner() == vp_nfs[1] && compliance_nfs[1].inner() == vp_nfs[0])) { return Err(TransactionError::InconsistentNullifier); } // check resource_commitments - // Check the vp actually uses the output resources from action circuits. + // Check the vp actually uses the output resources from compliance circuits. let vp_cms = [ public_inputs.get_from_index(VP_CIRCUIT_OUTPUT_CM_ONE_PUBLIC_INPUT_IDX), public_inputs.get_from_index(VP_CIRCUIT_OUTPUT_CM_TWO_PUBLIC_INPUT_IDX), ]; - if !((action_cms[0].inner() == vp_cms[0] && action_cms[1].inner() == vp_cms[1]) - || (action_cms[0].inner() == vp_cms[1] && action_cms[1].inner() == vp_cms[0])) + if !((compliance_cms[0].inner() == vp_cms[0] && compliance_cms[1].inner() == vp_cms[1]) + || (compliance_cms[0].inner() == vp_cms[1] && compliance_cms[1].inner() == vp_cms[0])) { return Err(TransactionError::InconsistentOutputResourceCommitment); } @@ -165,14 +165,14 @@ impl ApplicationByteCode { // Verify vp circuits transparently and return owned resource PubID for further checking pub fn verify_transparently( &self, - action_nfs: &[Nullifier], - action_cms: &[ResourceCommitment], + compliance_nfs: &[Nullifier], + compliance_cms: &[ResourceCommitment], ) -> Result { let owned_resource_id = self .app_vp_bytecode - .verify_transparently(action_nfs, action_cms)?; + .verify_transparently(compliance_nfs, compliance_cms)?; for dynamic_vp in self.dynamic_vp_bytecode.iter() { - let id = dynamic_vp.verify_transparently(action_nfs, action_cms)?; + let id = dynamic_vp.verify_transparently(compliance_nfs, compliance_cms)?; // check: the app_vp and dynamic_vps belong to the resource if id != owned_resource_id { return Err(TransactionError::InconsistentOwneResourceID); diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/compliance.rs similarity index 86% rename from taiga_halo2/src/action.rs rename to taiga_halo2/src/compliance.rs index 0fc771e3..060b869b 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/compliance.rs @@ -1,5 +1,11 @@ +/// A resource machine compliance proof is required to ensure that the provided transaction is well-formed. +/// This proof, among other checks, includes the check that the resource was created only once, was consumed +/// only once and strictly after it was created. Its commitment and nullifier must be derived correctly according +/// to the rules for commitment/nullifier derivation. It also requires explicit check of the presence of all +/// other required proofs + use crate::{ - circuit::action_circuit::ActionCircuit, + circuit::compliance_circuit::ComplianceCircuit, constant::{PRF_EXPAND_INPUT_VP_CM_R, PRF_EXPAND_OUTPUT_VP_CM_R}, delta_commitment::DeltaCommitment, merkle_tree::{Anchor, MerklePath}, @@ -19,12 +25,12 @@ use serde; #[cfg(feature = "borsh")] use borsh::{BorshDeserialize, BorshSerialize}; -/// The public inputs of action proof. +/// The public inputs of compliance proof. #[derive(Debug, Clone)] #[cfg_attr(feature = "nif", derive(NifStruct))] -#[cfg_attr(feature = "nif", module = "Taiga.Action.PublicInputs")] +#[cfg_attr(feature = "nif", module = "Taiga.Compliance.PublicInputs")] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ActionPublicInputs { +pub struct CompliancePublicInputs { /// The root of the resource commitment Merkle tree. pub anchor: Anchor, /// The nullifier of input resource. @@ -39,11 +45,11 @@ pub struct ActionPublicInputs { pub output_vp_commitment: ValidityPredicateCommitment, } -/// The information to build ActionPublicInputs and ActionCircuit. +/// The information to build CompliancePublicInputs and ComplianceCircuit. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] -pub struct ActionInfo { +pub struct ComplianceInfo { input_resource: Resource, input_merkle_path: MerklePath, input_anchor: Anchor, @@ -52,7 +58,7 @@ pub struct ActionInfo { rseed: RandomSeed, } -impl ActionPublicInputs { +impl CompliancePublicInputs { 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(); @@ -71,7 +77,7 @@ impl ActionPublicInputs { } #[cfg(feature = "borsh")] -impl BorshSerialize for ActionPublicInputs { +impl BorshSerialize for CompliancePublicInputs { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.anchor.to_bytes())?; writer.write_all(&self.nf.to_bytes())?; @@ -84,7 +90,7 @@ impl BorshSerialize for ActionPublicInputs { } #[cfg(feature = "borsh")] -impl BorshDeserialize for ActionPublicInputs { +impl BorshDeserialize for CompliancePublicInputs { fn deserialize_reader(reader: &mut R) -> std::io::Result { use std::io; let anchor_bytes = <[u8; 32]>::deserialize_reader(reader)?; @@ -106,7 +112,7 @@ impl BorshDeserialize for ActionPublicInputs { let output_vp_commitment = ValidityPredicateCommitment::from_bytes(output_vp_commitment_bytes); - Ok(ActionPublicInputs { + Ok(CompliancePublicInputs { anchor, nf, cm, @@ -117,7 +123,7 @@ impl BorshDeserialize for ActionPublicInputs { } } -impl ActionInfo { +impl ComplianceInfo { // The dummy input resource must provide a valid custom_anchor, but a random merkle path // The normal input resource only needs to provide a valid merkle path. The anchor will be calculated from the resource and path. // The nonce of output_resource will be set to the nullifier of input_resource @@ -177,7 +183,7 @@ impl ActionInfo { self.output_resource.commitment() } - pub fn build(&self) -> (ActionPublicInputs, ActionCircuit) { + pub fn build(&self) -> (CompliancePublicInputs, ComplianceCircuit) { let nf = self.get_input_resource_nullifer(); assert_eq!( nf, self.output_resource.nonce, @@ -197,7 +203,7 @@ impl ActionInfo { let output_vp_commitment = ValidityPredicateCommitment::commit(&self.output_resource.get_logic(), &output_vp_cm_r); - let action = ActionPublicInputs { + let compliance = CompliancePublicInputs { nf, cm, anchor: self.input_anchor, @@ -206,7 +212,7 @@ impl ActionInfo { output_vp_commitment, }; - let action_circuit = ActionCircuit { + let compliance_circuit = ComplianceCircuit { input_resource: self.input_resource, merkle_path: self.input_merkle_path.get_path().try_into().unwrap(), output_resource: self.output_resource, @@ -215,23 +221,23 @@ impl ActionInfo { output_vp_cm_r, }; - (action, action_circuit) + (compliance, compliance_circuit) } } #[cfg(test)] pub mod tests { - use super::ActionInfo; + use super::ComplianceInfo; use crate::constant::TAIGA_COMMITMENT_TREE_DEPTH; use crate::merkle_tree::MerklePath; use crate::resource::tests::random_resource; use rand::RngCore; - pub fn random_action_info(mut rng: R) -> ActionInfo { + pub fn random_compliance_info(mut rng: R) -> ComplianceInfo { let input_resource = random_resource(&mut rng); let mut output_resource = random_resource(&mut rng); let input_merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - ActionInfo::new( + ComplianceInfo::new( input_resource, input_merkle_path, None, diff --git a/taiga_halo2/src/constant.rs b/taiga_halo2/src/constant.rs index 41711d12..eb74f732 100644 --- a/taiga_halo2/src/constant.rs +++ b/taiga_halo2/src/constant.rs @@ -1,4 +1,4 @@ -use crate::circuit::action_circuit::ActionCircuit; +use crate::circuit::compliance_circuit::ComplianceCircuit; use crate::utils::to_field_elements; use group::Group; use halo2_gadgets::{ @@ -44,15 +44,15 @@ pub const BASE_BITS_NUM: usize = 255; /// The number of resources in a (partial)tx. pub const NUM_RESOURCE: usize = 2; -pub const ACTION_NF_PUBLIC_INPUT_ROW_IDX: usize = 0; -pub const ACTION_ANCHOR_PUBLIC_INPUT_ROW_IDX: usize = 1; -pub const ACTION_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX: usize = 2; -pub const ACTION_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX: usize = 3; -pub const ACTION_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX: usize = 4; -pub const ACTION_INPUT_VP_CM_1_ROW_IDX: usize = 5; -pub const ACTION_INPUT_VP_CM_2_ROW_IDX: usize = 6; -pub const ACTION_OUTPUT_VP_CM_1_ROW_IDX: usize = 7; -pub const ACTION_OUTPUT_VP_CM_2_ROW_IDX: usize = 8; +pub const COMPLIANCE_NF_PUBLIC_INPUT_ROW_IDX: usize = 0; +pub const COMPLIANCE_ANCHOR_PUBLIC_INPUT_ROW_IDX: usize = 1; +pub const COMPLIANCE_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX: usize = 2; +pub const COMPLIANCE_DELTA_CM_X_PUBLIC_INPUT_ROW_IDX: usize = 3; +pub const COMPLIANCE_DELTA_CM_Y_PUBLIC_INPUT_ROW_IDX: usize = 4; +pub const COMPLIANCE_INPUT_VP_CM_1_ROW_IDX: usize = 5; +pub const COMPLIANCE_INPUT_VP_CM_2_ROW_IDX: usize = 6; +pub const COMPLIANCE_OUTPUT_VP_CM_1_ROW_IDX: usize = 7; +pub const COMPLIANCE_OUTPUT_VP_CM_2_ROW_IDX: usize = 8; pub const POSEIDON_TO_CURVE_INPUT_LEN: usize = 3; pub const CURVE_ID: &str = "pallas"; @@ -113,7 +113,7 @@ lazy_static! { } pub const PARAMS_SIZE: u32 = 15; -pub const ACTION_CIRCUIT_PARAMS_SIZE: u32 = PARAMS_SIZE; +pub const COMPLIANCE_CIRCUIT_PARAMS_SIZE: u32 = PARAMS_SIZE; pub const VP_CIRCUIT_PARAMS_SIZE: u32 = PARAMS_SIZE; // Setup params map @@ -130,13 +130,15 @@ lazy_static! { }; } -// Action proving key and verifying key +// Compliance proving key and verifying key lazy_static! { - pub static ref ACTION_VERIFYING_KEY: VerifyingKey = - ACTION_PROVING_KEY.get_vk().clone(); - pub static ref ACTION_PROVING_KEY: ProvingKey = { - let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); - let empty_circuit: ActionCircuit = Default::default(); + pub static ref COMPLIANCE_VERIFYING_KEY: VerifyingKey = + COMPLIANCE_PROVING_KEY.get_vk().clone(); + pub static ref COMPLIANCE_PROVING_KEY: ProvingKey = { + let params = SETUP_PARAMS_MAP + .get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE) + .unwrap(); + let empty_circuit: ComplianceCircuit = Default::default(); let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail") }; @@ -6135,17 +6137,17 @@ fn export_params() { // Consider loading the key from file when the keys are stablized. // #[ignore] // #[test] -// fn export_action_proving_key() { +// fn export_compliance_proving_key() { // use std::io::Write; -// let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); -// let empty_circuit: ActionCircuit = Default::default(); +// let params = SETUP_PARAMS_MAP.get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE).unwrap(); +// let empty_circuit: ComplianceCircuit = Default::default(); // let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); // let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); // let mut bytes = vec![]; // pk.write(&mut bytes).unwrap(); -// let mut file = std::fs::File::create("./params/action_proving_key") -// .unwrap_or_else(|err| panic!("cannot create action_proving_key with {}", err)); +// let mut file = std::fs::File::create("./params/compliance_proving_key") +// .unwrap_or_else(|err| panic!("cannot create compliance_proving_key with {}", err)); // file.write_all(&bytes).unwrap(); // } diff --git a/taiga_halo2/src/error.rs b/taiga_halo2/src/error.rs index 3b696593..4ac000a3 100644 --- a/taiga_halo2/src/error.rs +++ b/taiga_halo2/src/error.rs @@ -10,11 +10,11 @@ pub enum TransactionError { InvalidBindingSignature, /// Binding signature is missing. MissingBindingSignatures, - /// Nullifier is not consistent between the action and the vp. + /// Nullifier is not consistent between the compliance and the vp. InconsistentNullifier, - /// Output resource commitment is not consistent between the action and the vp. + /// Output resource commitment is not consistent between the compliance and the vp. InconsistentOutputResourceCommitment, - /// Owned resource id is not consistent between the action and the vp. + /// Owned resource id is not consistent between the compliance and the vp. InconsistentOwneResourceID, /// IO error IoError(std::io::Error), @@ -36,13 +36,13 @@ impl Display for TransactionError { InvalidBindingSignature => f.write_str("Binding signature was invalid"), MissingBindingSignatures => f.write_str("Binding signature is missing"), InconsistentNullifier => { - f.write_str("Nullifier is not consistent between the action and the vp") + f.write_str("Nullifier is not consistent between the compliance and the vp") } InconsistentOutputResourceCommitment => f.write_str( - "Output resource commitment is not consistent between the action and the vp", + "Output resource commitment is not consistent between the compliance and the vp", ), InconsistentOwneResourceID => { - f.write_str("Owned resource id is not consistent between the action and the vp") + f.write_str("Owned resource id is not consistent between the compliance and the vp") } IoError(e) => f.write_str(&format!("IoError error: {e}")), MissingTransparentResourceNullifierKey => { diff --git a/taiga_halo2/src/lib.rs b/taiga_halo2/src/lib.rs index 5aa88a66..974533c2 100644 --- a/taiga_halo2/src/lib.rs +++ b/taiga_halo2/src/lib.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] #![allow(clippy::large_enum_variant)] -pub mod action; pub mod binding_signature; pub mod circuit; +pub mod compliance; pub mod constant; pub mod delta_commitment; pub mod error; diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index 33034dea..b68dce64 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -104,7 +104,7 @@ pub struct Resource { pub psi: pallas::Base, /// rcm is the trapdoor of the resource commitment pub rcm: pallas::Base, - /// If the is_merkle_checked flag is true, the merkle path authorization(membership) of input resource will be checked in ActionProof. + /// If the is_merkle_checked flag is true, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. pub is_merkle_checked: bool, } @@ -157,7 +157,7 @@ impl Resource { } } - // The nonce, psi, and rcm are not specified until the action is constructed. + // The nonce, psi, and rcm are not specified until the compliance is constructed. #[allow(clippy::too_many_arguments)] pub fn new_output_resource( logic: pallas::Base, diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 301f0f2e..3ce386d0 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -1,8 +1,8 @@ -use crate::action::{ActionInfo, ActionPublicInputs}; use crate::circuit::vp_circuit::{VPVerifyingInfo, ValidityPredicate}; +use crate::compliance::{ComplianceInfo, CompliancePublicInputs}; use crate::constant::{ - ACTION_CIRCUIT_PARAMS_SIZE, ACTION_PROVING_KEY, ACTION_VERIFYING_KEY, MAX_DYNAMIC_VP_NUM, - NUM_RESOURCE, SETUP_PARAMS_MAP, + COMPLIANCE_CIRCUIT_PARAMS_SIZE, COMPLIANCE_PROVING_KEY, COMPLIANCE_VERIFYING_KEY, + MAX_DYNAMIC_VP_NUM, NUM_RESOURCE, SETUP_PARAMS_MAP, }; use crate::delta_commitment::DeltaCommitment; use crate::error::TransactionError; @@ -30,7 +30,7 @@ use ff::PrimeField; #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ShieldedPartialTransaction { - actions: [ActionVerifyingInfo; NUM_RESOURCE], + compliances: [ComplianceVerifyingInfo; NUM_RESOURCE], inputs: [ResourceVPVerifyingInfoSet; NUM_RESOURCE], outputs: [ResourceVPVerifyingInfoSet; NUM_RESOURCE], binding_sig_r: Option, @@ -42,9 +42,9 @@ pub struct ShieldedPartialTransaction { #[cfg_attr(feature = "nif", module = "Taiga.Action.VerifyingInfo")] #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ActionVerifyingInfo { - action_proof: Proof, - action_instance: ActionPublicInputs, +pub struct ComplianceVerifyingInfo { + compliance_proof: Proof, + compliance_instance: CompliancePublicInputs, } #[derive(Debug, Clone)] @@ -64,7 +64,7 @@ pub struct ResourceVPVerifyingInfoSet { #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Shielded.PTX")] struct ShieldedPartialTransactionProxy { - actions: Vec, + compliances: Vec, inputs: Vec, outputs: Vec, binding_sig_r: Option, @@ -73,7 +73,7 @@ struct ShieldedPartialTransactionProxy { impl ShieldedPartialTransaction { pub fn from_bytecode( - actions: Vec, + compliances: Vec, input_resource_app: Vec, output_resource_app: Vec, hints: Vec, @@ -88,16 +88,16 @@ impl ShieldedPartialTransaction { .map(|bytecode| bytecode.generate_proofs()) .collect(); let mut rcv_sum = pallas::Scalar::zero(); - let actions: Vec = actions + let compliances: Vec = compliances .iter() - .map(|action_info| { - rcv_sum += action_info.get_rcv(); - ActionVerifyingInfo::create(action_info, &mut rng).unwrap() + .map(|compliance_info| { + rcv_sum += compliance_info.get_rcv(); + ComplianceVerifyingInfo::create(compliance_info, &mut rng).unwrap() }) .collect(); Ok(Self { - actions: actions.try_into().unwrap(), + compliances: compliances.try_into().unwrap(), inputs: inputs?.try_into().unwrap(), outputs: outputs?.try_into().unwrap(), binding_sig_r: Some(rcv_sum), @@ -106,19 +106,19 @@ impl ShieldedPartialTransaction { } pub fn build( - action_pairs: Vec, + compliance_pairs: Vec, input_resource_vps: Vec, output_resource_vps: Vec, hints: Vec, mut rng: R, ) -> Result { - // Generate action proofs + // Generate compliance proofs let mut rcv_sum = pallas::Scalar::zero(); - let actions: Vec = action_pairs + let compliances: Vec = compliance_pairs .iter() - .map(|action_info| { - rcv_sum += action_info.get_rcv(); - ActionVerifyingInfo::create(action_info, &mut rng).unwrap() + .map(|compliance_info| { + rcv_sum += compliance_info.get_rcv(); + ComplianceVerifyingInfo::create(compliance_info, &mut rng).unwrap() }) .collect(); @@ -135,7 +135,7 @@ impl ShieldedPartialTransaction { .collect(); Ok(Self { - actions: actions.try_into().unwrap(), + compliances: compliances.try_into().unwrap(), inputs: inputs.try_into().unwrap(), outputs: outputs.try_into().unwrap(), binding_sig_r: Some(rcv_sum), @@ -145,8 +145,8 @@ impl ShieldedPartialTransaction { // verify zk proof pub fn verify_proof(&self) -> Result<(), TransactionError> { - // Verify action proofs - for verifying_info in self.actions.iter() { + // Verify compliance proofs + for verifying_info in self.compliances.iter() { verifying_info.verify()?; } @@ -162,22 +162,22 @@ impl ShieldedPartialTransaction { Ok(()) } - // check the nullifiers are from action proofs + // check the nullifiers are from compliance proofs fn check_nullifiers(&self) -> Result<(), TransactionError> { assert_eq!(NUM_RESOURCE, 2); - let action_nfs = self.get_nullifiers(); + let compliance_nfs = self.get_nullifiers(); for vp_info in self.inputs.iter().chain(self.outputs.iter()) { for nfs in vp_info.get_nullifiers().iter() { - // Check the vp actually uses the input resources from action circuits. - if !((action_nfs[0].inner() == nfs[0] && action_nfs[1].inner() == nfs[1]) - || (action_nfs[0].inner() == nfs[1] && action_nfs[1].inner() == nfs[0])) + // Check the vp actually uses the input resources from compliance circuits. + if !((compliance_nfs[0].inner() == nfs[0] && compliance_nfs[1].inner() == nfs[1]) + || (compliance_nfs[0].inner() == nfs[1] && compliance_nfs[1].inner() == nfs[0])) { return Err(TransactionError::InconsistentNullifier); } } } - for (vp_info, action_nf) in self.inputs.iter().zip(action_nfs.iter()) { + for (vp_info, compliance_nf) in self.inputs.iter().zip(compliance_nfs.iter()) { // Check the app vp and the sub vps use the same owned_resource_id in one resource let owned_resource_id = vp_info.app_vp_verifying_info.get_owned_resource_id(); for logic_vp_verifying_info in vp_info.app_dynamic_vp_verifying_info.iter() { @@ -186,30 +186,30 @@ impl ShieldedPartialTransaction { } } - // Check the owned_resource_id that vp uses is consistent with the nf from the action circuit - if owned_resource_id != action_nf.inner() { + // Check the owned_resource_id that vp uses is consistent with the nf from the compliance circuit + if owned_resource_id != compliance_nf.inner() { return Err(TransactionError::InconsistentOwneResourceID); } } Ok(()) } - // check the output cms are from action proofs + // check the output cms are from compliance proofs fn check_resource_commitments(&self) -> Result<(), TransactionError> { assert_eq!(NUM_RESOURCE, 2); - let action_cms = self.get_output_cms(); + let compliance_cms = self.get_output_cms(); for vp_info in self.inputs.iter().chain(self.outputs.iter()) { for cms in vp_info.get_resource_commitments().iter() { - // Check the vp actually uses the output resources from action circuits. - if !((action_cms[0] == cms[0] && action_cms[1] == cms[1]) - || (action_cms[0] == cms[1] && action_cms[1] == cms[0])) + // Check the vp actually uses the output resources from compliance circuits. + if !((compliance_cms[0] == cms[0] && compliance_cms[1] == cms[1]) + || (compliance_cms[0] == cms[1] && compliance_cms[1] == cms[0])) { return Err(TransactionError::InconsistentOutputResourceCommitment); } } } - for (vp_info, action_cm) in self.outputs.iter().zip(action_cms.iter()) { + for (vp_info, compliance_cm) in self.outputs.iter().zip(compliance_cms.iter()) { // Check that the app vp and the sub vps use the same owned_resource_id in one resource let owned_resource_id = vp_info.app_vp_verifying_info.get_owned_resource_id(); for logic_vp_verifying_info in vp_info.app_dynamic_vp_verifying_info.iter() { @@ -218,8 +218,8 @@ impl ShieldedPartialTransaction { } } - // Check the owned_resource_id that vp uses is consistent with the cm from the action circuit - if owned_resource_id != action_cm.inner() { + // Check the owned_resource_id that vp uses is consistent with the cm from the compliance circuit + if owned_resource_id != compliance_cm.inner() { return Err(TransactionError::InconsistentOwneResourceID); } } @@ -229,7 +229,7 @@ impl ShieldedPartialTransaction { // Conversion to the generic length proxy fn to_proxy(&self) -> ShieldedPartialTransactionProxy { ShieldedPartialTransactionProxy { - actions: self.actions.to_vec(), + compliances: self.compliances.to_vec(), inputs: self.inputs.to_vec(), outputs: self.outputs.to_vec(), binding_sig_r: self.binding_sig_r, @@ -253,11 +253,11 @@ impl ShieldedPartialTransaction { impl ShieldedPartialTransactionProxy { fn to_concrete(&self) -> Option { - let actions = self.actions.clone().try_into().ok()?; + let compliances = self.compliances.clone().try_into().ok()?; let inputs = self.inputs.clone().try_into().ok()?; let outputs = self.outputs.clone().try_into().ok()?; Some(ShieldedPartialTransaction { - actions, + compliances, inputs, outputs, binding_sig_r: self.binding_sig_r, @@ -275,30 +275,30 @@ impl Executable for ShieldedPartialTransaction { } fn get_nullifiers(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.action_instance.nf) + .map(|compliance| compliance.compliance_instance.nf) .collect() } fn get_output_cms(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.action_instance.cm) + .map(|compliance| compliance.compliance_instance.cm) .collect() } fn get_delta_commitments(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.action_instance.delta) + .map(|compliance| compliance.compliance_instance.delta) .collect() } fn get_anchors(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.action_instance.anchor) + .map(|compliance| compliance.compliance_instance.anchor) .collect() } } @@ -307,8 +307,8 @@ impl Executable for ShieldedPartialTransaction { impl BorshSerialize for ShieldedPartialTransaction { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { use byteorder::WriteBytesExt; - for action in self.actions.iter() { - action.serialize(writer)?; + for compliance in self.compliances.iter() { + compliance.serialize(writer)?; } for input in self.inputs.iter() { @@ -340,8 +340,8 @@ impl BorshSerialize for ShieldedPartialTransaction { impl BorshDeserialize for ShieldedPartialTransaction { fn deserialize_reader(reader: &mut R) -> std::io::Result { use byteorder::ReadBytesExt; - let actions: Vec<_> = (0..NUM_RESOURCE) - .map(|_| ActionVerifyingInfo::deserialize_reader(reader)) + let compliances: Vec<_> = (0..NUM_RESOURCE) + .map(|_| ComplianceVerifyingInfo::deserialize_reader(reader)) .collect::>()?; let inputs: Vec<_> = (0..NUM_RESOURCE) .map(|_| ResourceVPVerifyingInfoSet::deserialize_reader(reader)) @@ -366,7 +366,7 @@ impl BorshDeserialize for ShieldedPartialTransaction { let hints = Vec::::deserialize_reader(reader)?; Ok(ShieldedPartialTransaction { - actions: actions.try_into().unwrap(), + compliances: compliances.try_into().unwrap(), inputs: inputs.try_into().unwrap(), outputs: outputs.try_into().unwrap(), binding_sig_r, @@ -391,29 +391,33 @@ impl<'a> Decoder<'a> for ShieldedPartialTransaction { } } -impl ActionVerifyingInfo { - pub fn create(action_info: &ActionInfo, mut rng: R) -> Result { - let (action_instance, circuit) = action_info.build(); - let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); - let action_proof = Proof::create( - &ACTION_PROVING_KEY, +impl ComplianceVerifyingInfo { + pub fn create(compliance_info: &ComplianceInfo, mut rng: R) -> Result { + let (compliance_instance, circuit) = compliance_info.build(); + let params = SETUP_PARAMS_MAP + .get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE) + .unwrap(); + let compliance_proof = Proof::create( + &COMPLIANCE_PROVING_KEY, params, circuit, - &[&action_instance.to_instance()], + &[&compliance_instance.to_instance()], &mut rng, )?; Ok(Self { - action_proof, - action_instance, + compliance_proof, + compliance_instance, }) } pub fn verify(&self) -> Result<(), Error> { - let params = SETUP_PARAMS_MAP.get(&ACTION_CIRCUIT_PARAMS_SIZE).unwrap(); - self.action_proof.verify( - &ACTION_VERIFYING_KEY, + let params = SETUP_PARAMS_MAP + .get(&COMPLIANCE_CIRCUIT_PARAMS_SIZE) + .unwrap(); + self.compliance_proof.verify( + &COMPLIANCE_VERIFYING_KEY, params, - &[&self.action_instance.to_instance()], + &[&self.compliance_instance.to_instance()], ) } } @@ -485,9 +489,9 @@ impl ResourceVPVerifyingInfoSet { #[cfg(test)] pub mod testing { use crate::{ - action::ActionInfo, circuit::vp_circuit::{ValidityPredicate, ValidityPredicateVerifyingInfo}, circuit::vp_examples::TrivialValidityPredicateCircuit, + compliance::ComplianceInfo, constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::MerklePath, nullifier::Nullifier, @@ -550,9 +554,9 @@ pub mod testing { ) }; - // Construct action pair + // Construct compliance pair let merkle_path_1 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_1 = ActionInfo::new( + let compliance_1 = ComplianceInfo::new( input_resource_1, merkle_path_1, None, @@ -596,9 +600,9 @@ pub mod testing { ) }; - // Construct action pair + // Construct compliance pair let merkle_path_2 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( input_resource_2, merkle_path_2, None, @@ -636,7 +640,7 @@ pub mod testing { // Create shielded partial tx ShieldedPartialTransaction::build( - vec![action_1, action_2], + vec![compliance_1, compliance_2], vec![input_resource_1_vps, input_resource_2_vps], vec![output_resource_1_vps, output_resource_2_vps], vec![], diff --git a/taiga_halo2/src/taiga_api.rs b/taiga_halo2/src/taiga_api.rs index 5f32e57e..e6601b5f 100644 --- a/taiga_halo2/src/taiga_api.rs +++ b/taiga_halo2/src/taiga_api.rs @@ -1,6 +1,7 @@ #[cfg(feature = "borsh")] use crate::{ - action::ActionInfo, circuit::vp_bytecode::ApplicationByteCode, transaction::TransactionResult, + circuit::vp_bytecode::ApplicationByteCode, compliance::ComplianceInfo, + transaction::TransactionResult, }; use crate::{ error::TransactionError, @@ -104,7 +105,7 @@ pub fn resource_deserialize(bytes: Vec) -> std::io::Result { /// Shielded Partial Transaction layout: /// | Parameters | type | size(bytes) | /// | - | - | - | -/// | 2 action proofs | ActionVerifyingInfo | 4676 * 2 | +/// | 2 compliance proofs | ComplianceVerifyingInfo| 4676 * 2 | /// | input1 static vp proof | VPVerifyingInfo | 158216 | /// | input1 dynamic vp num(by borsh) | u32 | 4 | /// | input1 dynamic vp proof | VPVerifyingInfo | 158216 * num | @@ -160,14 +161,14 @@ pub fn transaction_deserialize(bytes: Vec) -> std::io::Result { /// Create a shielded partial transaction from vp bytecode #[cfg(feature = "borsh")] pub fn create_shielded_partial_transaction( - actions: Vec, + compliances: Vec, input_resource_app: Vec, output_resource_app: Vec, hints: Vec, ) -> Result { let rng = OsRng; ShieldedPartialTransaction::from_bytecode( - actions, + compliances, input_resource_app, output_resource_app, hints, @@ -252,8 +253,8 @@ pub mod tests { // #[ignore] #[test] fn ptx_example_test() { - use crate::action::ActionInfo; use crate::circuit::vp_examples::TrivialValidityPredicateCircuit; + use crate::compliance::ComplianceInfo; use crate::constant::TAIGA_COMMITMENT_TREE_DEPTH; use crate::merkle_tree::MerklePath; use crate::resource::tests::random_resource; @@ -265,7 +266,7 @@ pub mod tests { let input_resource_1_nf = input_resource_1.get_nf().unwrap(); let mut output_resource_1 = random_resource(&mut rng); let merkle_path_1 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_1 = ActionInfo::new( + let compliance_1 = ComplianceInfo::new( input_resource_1, merkle_path_1, None, @@ -277,7 +278,7 @@ pub mod tests { let input_resource_2_nf = input_resource_2.get_nf().unwrap(); let mut output_resource_2 = random_resource(&mut rng); let merkle_path_2 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( input_resource_2, merkle_path_2, None, @@ -328,7 +329,7 @@ pub mod tests { // construct ptx let ptx = create_shielded_partial_transaction( - vec![action_1, action_2], + vec![compliance_1, compliance_2], vec![input_resource_1_app, input_resource_2_app], vec![output_resource_1_app, output_resource_2_app], vec![], diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index 5a878bab..9f6963b9 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -1,5 +1,5 @@ use crate::{ - action::ActionInfo, circuit::vp_bytecode::ApplicationByteCode, constant::NUM_RESOURCE, + circuit::vp_bytecode::ApplicationByteCode, compliance::ComplianceInfo, constant::NUM_RESOURCE, delta_commitment::DeltaCommitment, error::TransactionError, executable::Executable, merkle_tree::Anchor, nullifier::Nullifier, resource::ResourceCommitment, }; @@ -15,7 +15,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TransparentPartialTransaction { - actions: Vec, + compliances: Vec, input_resource_app: Vec, output_resource_app: Vec, hints: Vec, @@ -23,17 +23,17 @@ pub struct TransparentPartialTransaction { impl TransparentPartialTransaction { pub fn new( - actions: Vec, + compliances: Vec, input_resource_app: Vec, output_resource_app: Vec, hints: Vec, ) -> Self { - assert_eq!(actions.len(), NUM_RESOURCE); + assert_eq!(compliances.len(), NUM_RESOURCE); assert_eq!(input_resource_app.len(), NUM_RESOURCE); assert_eq!(output_resource_app.len(), NUM_RESOURCE); Self { - actions, + compliances, input_resource_app, output_resource_app, hints, @@ -44,18 +44,18 @@ impl TransparentPartialTransaction { impl Executable for TransparentPartialTransaction { fn execute(&self) -> Result<(), TransactionError> { // check VPs, nullifiers, and resource commitments - let action_nfs = self.get_nullifiers(); - let action_cms = self.get_output_cms(); - for (vp, nf) in self.input_resource_app.iter().zip(action_nfs.iter()) { - let owned_resource_id = vp.verify_transparently(&action_nfs, &action_cms)?; + let compliance_nfs = self.get_nullifiers(); + let compliance_cms = self.get_output_cms(); + for (vp, nf) in self.input_resource_app.iter().zip(compliance_nfs.iter()) { + let owned_resource_id = vp.verify_transparently(&compliance_nfs, &compliance_cms)?; // Check all resources are checked if owned_resource_id != nf.inner() { return Err(TransactionError::InconsistentOwneResourceID); } } - for (vp, cm) in self.output_resource_app.iter().zip(action_cms.iter()) { - let owned_resource_id = vp.verify_transparently(&action_nfs, &action_cms)?; + for (vp, cm) in self.output_resource_app.iter().zip(compliance_cms.iter()) { + let owned_resource_id = vp.verify_transparently(&compliance_nfs, &compliance_cms)?; // Check all resources are checked if owned_resource_id != cm.inner() { return Err(TransactionError::InconsistentOwneResourceID); @@ -65,35 +65,35 @@ impl Executable for TransparentPartialTransaction { Ok(()) } - // get nullifiers from actions + // get nullifiers from compliances fn get_nullifiers(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.get_input_resource_nullifer()) + .map(|compliance| compliance.get_input_resource_nullifer()) .collect() } - // get output cms from actions + // get output cms from compliances fn get_output_cms(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.get_output_resource_cm()) + .map(|compliance| compliance.get_output_resource_cm()) .collect() } fn get_delta_commitments(&self) -> Vec { - self.actions + self.compliances .iter() - .map(|action| action.get_delta_commitment(&pallas::Scalar::zero())) + .map(|compliance| compliance.get_delta_commitment(&pallas::Scalar::zero())) .collect() } fn get_anchors(&self) -> Vec { // TODO: We have easier way to check the anchor in transparent scenario, but keep consistent with sheilded right now. // TODO: we can skip the root if the is_merkle_checked flag is false? - self.actions + self.compliances .iter() - .map(|action| action.calculate_root()) + .map(|compliance| compliance.calculate_root()) .collect() } } @@ -119,7 +119,7 @@ pub mod testing { resource }; let merkle_path_1 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_1 = ActionInfo::new( + let compliance_1 = ComplianceInfo::new( input_resource_1, merkle_path_1, None, @@ -135,7 +135,7 @@ pub mod testing { resource }; let merkle_path_2 = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); - let action_2 = ActionInfo::new( + let compliance_2 = ComplianceInfo::new( input_resource_2, merkle_path_2, None, @@ -185,7 +185,7 @@ pub mod testing { }; TransparentPartialTransaction::new( - vec![action_1, action_2], + vec![compliance_1, compliance_2], vec![input_resource_1_app, input_resource_2_app], vec![output_resource_1_app, output_resource_2_app], vec![], From 80cd7d1761d6f6e90eda767d33b60600bbf3f31f Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Wed, 29 Nov 2023 19:20:41 +0800 Subject: [PATCH 2/5] rename is_merkle_checked to is_ephemeral --- taiga_halo2/benches/compliance_proof.rs | 4 +- taiga_halo2/benches/vp_proof.rs | 4 +- taiga_halo2/src/circuit/compliance_circuit.rs | 15 ++--- taiga_halo2/src/circuit/integrity.rs | 28 ++++----- .../src/circuit/resource_commitment.rs | 60 +++++++++---------- taiga_halo2/src/circuit/vp_circuit.rs | 8 +-- taiga_halo2/src/circuit/vp_examples/token.rs | 12 ++-- taiga_halo2/src/compliance.rs | 1 - taiga_halo2/src/resource.rs | 42 ++++++------- taiga_halo2/src/shielded_ptx.rs | 16 ++--- taiga_halo2/src/taiga_api.rs | 12 ++-- taiga_halo2/src/transparent_ptx.rs | 2 +- 12 files changed, 96 insertions(+), 108 deletions(-) diff --git a/taiga_halo2/benches/compliance_proof.rs b/taiga_halo2/benches/compliance_proof.rs index 0df94f7c..2e64c961 100644 --- a/taiga_halo2/benches/compliance_proof.rs +++ b/taiga_halo2/benches/compliance_proof.rs @@ -37,7 +37,7 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: nk, - is_merkle_checked: true, + is_ephemeral: true, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, @@ -59,7 +59,7 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: npk, - is_merkle_checked: true, + is_ephemeral: true, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/benches/vp_proof.rs b/taiga_halo2/benches/vp_proof.rs index 09bc51c6..c7e9a25b 100644 --- a/taiga_halo2/benches/vp_proof.rs +++ b/taiga_halo2/benches/vp_proof.rs @@ -33,7 +33,7 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: nk, - is_merkle_checked: true, + is_ephemeral: true, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, @@ -57,7 +57,7 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: npk, - is_merkle_checked: true, + is_ephemeral: true, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/src/circuit/compliance_circuit.rs b/taiga_halo2/src/circuit/compliance_circuit.rs index 2d4b4e41..c102ca4c 100644 --- a/taiga_halo2/src/circuit/compliance_circuit.rs +++ b/taiga_halo2/src/circuit/compliance_circuit.rs @@ -125,15 +125,15 @@ impl Circuit for ComplianceCircuit { let merkle_path_selector = meta.selector(); meta.create_gate("merkle path check", |meta| { let merkle_path_selector = meta.query_selector(merkle_path_selector); - let is_merkle_checked_input = meta.query_advice(advices[0], Rotation::cur()); + let is_ephemeral_input = meta.query_advice(advices[0], Rotation::cur()); let anchor = meta.query_advice(advices[1], Rotation::cur()); let root = meta.query_advice(advices[2], Rotation::cur()); Constraints::with_selector( merkle_path_selector, [( - "is_merkle_checked is false, or root = anchor", - is_merkle_checked_input * (root - anchor), + "is_ephemeral is false, or root = anchor", + is_ephemeral_input * (root - anchor), )], ) }); @@ -262,13 +262,8 @@ impl Circuit for ComplianceCircuit { |mut region| { input_resource_variables .resource_variables - .is_merkle_checked - .copy_advice( - || "is_merkle_checked_input", - &mut region, - config.advices[0], - 0, - )?; + .is_ephemeral + .copy_advice(|| "is_ephemeral_input", &mut region, config.advices[0], 0)?; region.assign_advice_from_instance( || "anchor", config.instances, diff --git a/taiga_halo2/src/circuit/integrity.rs b/taiga_halo2/src/circuit/integrity.rs index 27ea9b5c..f9410770 100644 --- a/taiga_halo2/src/circuit/integrity.rs +++ b/taiga_halo2/src/circuit/integrity.rs @@ -118,12 +118,12 @@ pub fn check_input_resource( Value::known(input_resource.get_rcm()), )?; - // Witness is_merkle_checked - // is_merkle_checked will be boolean-constrained in the resource_commit. - let is_merkle_checked = assign_free_advice( - layouter.namespace(|| "witness is_merkle_checked"), + // Witness is_ephemeral + // is_ephemeral will be boolean-constrained in the resource_commit. + let is_ephemeral = assign_free_advice( + layouter.namespace(|| "witness is_ephemeral"), advices[0], - Value::known(pallas::Base::from(input_resource.is_merkle_checked)), + Value::known(pallas::Base::from(input_resource.is_ephemeral)), )?; // Check resource commitment @@ -137,7 +137,7 @@ pub fn check_input_resource( nonce.clone(), psi.clone(), quantity.clone(), - is_merkle_checked.clone(), + is_ephemeral.clone(), rcm.clone(), )?; @@ -158,7 +158,7 @@ pub fn check_input_resource( logic, quantity, label, - is_merkle_checked, + is_ephemeral, value, nonce, npk, @@ -232,12 +232,12 @@ pub fn check_output_resource( Value::known(output_resource.get_psi()), )?; - // Witness is_merkle_checked - // is_merkle_checked will be boolean-constrained in the resource_commit. - let is_merkle_checked = assign_free_advice( - layouter.namespace(|| "witness is_merkle_checked"), + // Witness is_ephemeral + // is_ephemeral will be boolean-constrained in the resource_commit. + let is_ephemeral = assign_free_advice( + layouter.namespace(|| "witness is_ephemeral"), advices[0], - Value::known(pallas::Base::from(output_resource.is_merkle_checked)), + Value::known(pallas::Base::from(output_resource.is_ephemeral)), )?; // Check resource commitment @@ -251,7 +251,7 @@ pub fn check_output_resource( old_nf.clone(), psi.clone(), quantity.clone(), - is_merkle_checked.clone(), + is_ephemeral.clone(), rcm.clone(), )?; @@ -262,7 +262,7 @@ pub fn check_output_resource( logic, label, quantity, - is_merkle_checked, + is_ephemeral, value, nonce: old_nf, npk, diff --git a/taiga_halo2/src/circuit/resource_commitment.rs b/taiga_halo2/src/circuit/resource_commitment.rs index 439a7251..e1ed169c 100644 --- a/taiga_halo2/src/circuit/resource_commitment.rs +++ b/taiga_halo2/src/circuit/resource_commitment.rs @@ -11,16 +11,16 @@ use halo2_proofs::{ }; use pasta_curves::pallas; -/// compose = is_merkle_checked(bool) * 2^128 + quantity(64 bits) +/// compose = is_ephemeral(bool) * 2^128 + quantity(64 bits) #[derive(Clone, Debug)] -struct ComposeMerkleCheckQuantity { +struct ComposeIsEphemeralQuantity { q_compose: Selector, col_l: Column, col_m: Column, col_r: Column, } -impl ComposeMerkleCheckQuantity { +impl ComposeIsEphemeralQuantity { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -30,24 +30,21 @@ impl ComposeMerkleCheckQuantity { ) -> Self { let q_compose = meta.selector(); - meta.create_gate("Compose is_merkle_checked and quantity", |meta| { + meta.create_gate("Compose is_ephemeral and quantity", |meta| { let q_compose = meta.query_selector(q_compose); - let compose_is_merkle_checked_and_quantity = meta.query_advice(col_l, Rotation::cur()); - let is_merkle_checked = meta.query_advice(col_m, Rotation::cur()); + let compose_is_ephemeral_and_quantity = meta.query_advice(col_l, Rotation::cur()); + let is_ephemeral = meta.query_advice(col_m, Rotation::cur()); let quantity = meta.query_advice(col_r, Rotation::cur()); - // e = quantity + (2^128) * is_merkle_checked - let composition_check = compose_is_merkle_checked_and_quantity - - (quantity + is_merkle_checked.clone() * two_pow_128); + // e = quantity + (2^128) * is_ephemeral + let composition_check = + compose_is_ephemeral_and_quantity - (quantity + is_ephemeral.clone() * two_pow_128); Constraints::with_selector( q_compose, [ - ( - "bool_check is_merkle_checked", - bool_check(is_merkle_checked), - ), + ("bool_check is_ephemeral", bool_check(is_ephemeral)), ("composition", composition_check), ], ) @@ -64,25 +61,22 @@ impl ComposeMerkleCheckQuantity { fn assign( &self, layouter: &mut impl Layouter, - is_merkle_checked: &AssignedCell, + is_ephemeral: &AssignedCell, quantity: &AssignedCell, ) -> Result, Error> { layouter.assign_region( - || "Compose is_merkle_checked and quantity", + || "Compose is_ephemeral and quantity", |mut region| { self.q_compose.enable(&mut region, 0)?; - let compose = is_merkle_checked.value().zip(quantity.value()).map( - |(is_merkle_checked, quantity)| { - quantity + is_merkle_checked * pallas::Base::from_u128(1 << 64).square() - }, - ); - is_merkle_checked.copy_advice( - || "is_merkle_checked", - &mut region, - self.col_m, - 0, - )?; + let compose = + is_ephemeral + .value() + .zip(quantity.value()) + .map(|(is_ephemeral, quantity)| { + quantity + is_ephemeral * pallas::Base::from_u128(1 << 64).square() + }); + is_ephemeral.copy_advice(|| "is_ephemeral", &mut region, self.col_m, 0)?; quantity.copy_advice(|| "quantity", &mut region, self.col_r, 0)?; region.assign_advice(|| "compose", self.col_l, 0, || compose) @@ -93,7 +87,7 @@ impl ComposeMerkleCheckQuantity { #[derive(Clone, Debug)] pub struct ResourceCommitConfig { - compose_config: ComposeMerkleCheckQuantity, + compose_config: ComposeIsEphemeralQuantity, poseidon_config: PoseidonConfig, lookup_config: LookupRangeCheckConfig, } @@ -111,7 +105,7 @@ impl ResourceCommitChip { lookup_config: LookupRangeCheckConfig, ) -> ResourceCommitConfig { let two_pow_128 = pallas::Base::from_u128(1 << 64).square(); - let compose_config = ComposeMerkleCheckQuantity::configure( + let compose_config = ComposeIsEphemeralQuantity::configure( meta, advices[0], advices[1], @@ -150,14 +144,14 @@ pub fn resource_commit( nonce: AssignedCell, psi: AssignedCell, quantity: AssignedCell, - is_merkle_checked: AssignedCell, + is_ephemeral: AssignedCell, rcm: AssignedCell, ) -> Result, Error> { - // Compose the quantity and is_merkle_checked to one field in order to save one poseidon absorb - let compose_is_merkle_checked_and_quantity = + // Compose the quantity and is_ephemeral to one field in order to save one poseidon absorb + let compose_is_ephemeral_and_quantity = chip.config .compose_config - .assign(&mut layouter, &is_merkle_checked, &quantity)?; + .assign(&mut layouter, &is_ephemeral, &quantity)?; // resource commitment let poseidon_message = [ @@ -167,7 +161,7 @@ pub fn resource_commit( npk, nonce, psi, - compose_is_merkle_checked_and_quantity, + compose_is_ephemeral_and_quantity, rcm, ]; poseidon_hash_gadget( diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index 566e2019..7f3b5f88 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -571,7 +571,7 @@ pub struct ResourceVariables { pub logic: AssignedCell, pub label: AssignedCell, pub quantity: AssignedCell, - pub is_merkle_checked: AssignedCell, + pub is_ephemeral: AssignedCell, pub value: AssignedCell, pub nonce: AssignedCell, pub npk: AssignedCell, @@ -678,12 +678,12 @@ impl BasicValidityPredicateVariables { ) } - pub fn get_is_merkle_checked_searchable_pairs( + pub fn get_is_ephemeral_searchable_pairs( &self, ) -> [ResourceSearchableVariablePair; NUM_RESOURCE * 2] { self.get_variable_searchable_pairs( - |variables| variables.resource_variables.is_merkle_checked.clone(), - |variables| variables.resource_variables.is_merkle_checked.clone(), + |variables| variables.resource_variables.is_ephemeral.clone(), + |variables| variables.resource_variables.is_ephemeral.clone(), ) } diff --git a/taiga_halo2/src/circuit/vp_examples/token.rs b/taiga_halo2/src/circuit/vp_examples/token.rs index 628c76df..e53046e7 100644 --- a/taiga_halo2/src/circuit/vp_examples/token.rs +++ b/taiga_halo2/src/circuit/vp_examples/token.rs @@ -373,12 +373,12 @@ impl ValidityPredicateCircuit for TokenValidityPredicateCircuit { |mut region| region.constrain_equal(encoded_value.cell(), value.cell()), )?; - // check the is_merkle_checked flag - let is_merkle_checked = get_owned_resource_variable( + // check the is_ephemeral flag + let is_ephemeral = get_owned_resource_variable( config.get_owned_resource_variable_config, - layouter.namespace(|| "get is_merkle_checked"), + layouter.namespace(|| "get is_ephemeral"), &owned_resource_id, - &basic_variables.get_is_merkle_checked_searchable_pairs(), + &basic_variables.get_is_ephemeral_searchable_pairs(), )?; let constant_one = assign_free_constant( layouter.namespace(|| "one"), @@ -386,8 +386,8 @@ impl ValidityPredicateCircuit for TokenValidityPredicateCircuit { pallas::Base::one(), )?; layouter.assign_region( - || "check is_merkle_checked", - |mut region| region.constrain_equal(is_merkle_checked.cell(), constant_one.cell()), + || "check is_ephemeral", + |mut region| region.constrain_equal(is_ephemeral.cell(), constant_one.cell()), )?; // VP Commitment diff --git a/taiga_halo2/src/compliance.rs b/taiga_halo2/src/compliance.rs index 060b869b..8ddf36dc 100644 --- a/taiga_halo2/src/compliance.rs +++ b/taiga_halo2/src/compliance.rs @@ -3,7 +3,6 @@ /// only once and strictly after it was created. Its commitment and nullifier must be derived correctly according /// to the rules for commitment/nullifier derivation. It also requires explicit check of the presence of all /// other required proofs - use crate::{ circuit::compliance_circuit::ComplianceCircuit, constant::{PRF_EXPAND_INPUT_VP_CM_R, PRF_EXPAND_OUTPUT_VP_CM_R}, diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index b68dce64..90a9c72d 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -104,8 +104,8 @@ pub struct Resource { pub psi: pallas::Base, /// rcm is the trapdoor of the resource commitment pub rcm: pallas::Base, - /// If the is_merkle_checked flag is true, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. - pub is_merkle_checked: bool, + /// If the is_ephemeral flag is true, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. + pub is_ephemeral: bool, } /// The parameters in the ResourceKind are used to derive resource kind. @@ -141,7 +141,7 @@ impl Resource { quantity: u64, nk: pallas::Base, nonce: Nullifier, - is_merkle_checked: bool, + is_ephemeral: bool, rseed: RandomSeed, ) -> Self { let kind = ResourceKind::new(logic, label); @@ -150,7 +150,7 @@ impl Resource { value, quantity, nk_container: NullifierKeyContainer::Key(nk), - is_merkle_checked, + is_ephemeral, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, @@ -165,7 +165,7 @@ impl Resource { value: pallas::Base, quantity: u64, npk: pallas::Base, - is_merkle_checked: bool, + is_ephemeral: bool, ) -> Self { let kind = ResourceKind::new(logic, label); Self { @@ -173,7 +173,7 @@ impl Resource { value, quantity, nk_container: NullifierKeyContainer::PublicKey(npk), - is_merkle_checked, + is_ephemeral, psi: pallas::Base::default(), rcm: pallas::Base::default(), nonce: Nullifier::default(), @@ -188,7 +188,7 @@ impl Resource { quantity: u64, nk_container: NullifierKeyContainer, nonce: Nullifier, - is_merkle_checked: bool, + is_ephemeral: bool, psi: pallas::Base, rcm: pallas::Base, ) -> Self { @@ -198,7 +198,7 @@ impl Resource { value, quantity, nk_container, - is_merkle_checked, + is_ephemeral, psi, rcm, nonce, @@ -221,13 +221,13 @@ impl Resource { nonce, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), - is_merkle_checked: false, + is_ephemeral: false, } } - // resource_commitment = poseidon_hash(logic || label || value || npk || nonce || psi || is_merkle_checked || quantity || rcm) + // resource_commitment = poseidon_hash(logic || label || value || npk || nonce || psi || is_ephemeral || quantity || rcm) pub fn commitment(&self) -> ResourceCommitment { - let compose_is_merkle_checked_quantity = if self.is_merkle_checked { + let compose_is_ephemeral_quantity = if self.is_ephemeral { pallas::Base::from_u128(1 << 64).square() + pallas::Base::from(self.quantity) } else { pallas::Base::from(self.quantity) @@ -239,7 +239,7 @@ impl Resource { self.get_npk(), self.nonce.inner(), self.psi, - compose_is_merkle_checked_quantity, + compose_is_ephemeral_quantity, self.rcm, ]); ResourceCommitment(ret) @@ -325,8 +325,8 @@ impl BorshSerialize for Resource { writer.write_all(&self.psi.to_repr())?; // Write rcm writer.write_all(&self.rcm.to_repr())?; - // Write is_merkle_checked - writer.write_u8(if self.is_merkle_checked { 1 } else { 0 })?; + // Write is_ephemeral + writer.write_u8(if self.is_ephemeral { 1 } else { 0 })?; Ok(()) } @@ -382,11 +382,11 @@ impl BorshDeserialize for Resource { reader.read_exact(&mut rcm_bytes)?; let rcm = Option::from(pallas::Base::from_repr(rcm_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "rcm not in field"))?; - // Read is_merkle_checked - let mut is_merkle_checked_byte = [0u8; 1]; - reader.read_exact(&mut is_merkle_checked_byte)?; - let is_merkle_checked_byte = is_merkle_checked_byte[0]; - let is_merkle_checked = is_merkle_checked_byte == 0x01; + // Read is_ephemeral + let mut is_ephemeral_byte = [0u8; 1]; + reader.read_exact(&mut is_ephemeral_byte)?; + let is_ephemeral_byte = is_ephemeral_byte[0]; + let is_ephemeral = is_ephemeral_byte == 0x01; // Construct resource Ok(Resource::from_full( logic, @@ -395,7 +395,7 @@ impl BorshDeserialize for Resource { quantity, nk_container, nonce, - is_merkle_checked, + is_ephemeral, psi, rcm, )) @@ -579,7 +579,7 @@ pub mod tests { value: pallas::Base::random(&mut rng), quantity: rng.gen(), nk_container: random_nullifier_key(&mut rng), - is_merkle_checked: true, + is_ephemeral: true, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 3ce386d0..1954058b 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -524,7 +524,7 @@ pub mod testing { let quantity = 5000u64; let nk = pallas::Base::random(&mut rng); let rseed = RandomSeed::random(&mut rng); - let is_merkle_checked = true; + let is_ephemeral = true; Resource::new_input_resource( compressed_trivial_vp_vk, label, @@ -532,7 +532,7 @@ pub mod testing { quantity, nk, nonce, - is_merkle_checked, + is_ephemeral, rseed, ) }; @@ -543,14 +543,14 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 5000u64; let npk = pallas::Base::random(&mut rng); - let is_merkle_checked = true; + let is_ephemeral = true; Resource::new_output_resource( compressed_trivial_vp_vk, label, value, quantity, npk, - is_merkle_checked, + is_ephemeral, ) }; @@ -572,7 +572,7 @@ pub mod testing { let quantity = 10u64; let nk = pallas::Base::random(&mut rng); let rseed = RandomSeed::random(&mut rng); - let is_merkle_checked = true; + let is_ephemeral = true; Resource::new_input_resource( compressed_trivial_vp_vk, label, @@ -580,7 +580,7 @@ pub mod testing { quantity, nk, nonce, - is_merkle_checked, + is_ephemeral, rseed, ) }; @@ -589,14 +589,14 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 10u64; let npk = pallas::Base::random(&mut rng); - let is_merkle_checked = true; + let is_ephemeral = true; Resource::new_output_resource( compressed_trivial_vp_vk, label, value, quantity, npk, - is_merkle_checked, + is_ephemeral, ) }; diff --git a/taiga_halo2/src/taiga_api.rs b/taiga_halo2/src/taiga_api.rs index e6601b5f..7a80c9e3 100644 --- a/taiga_halo2/src/taiga_api.rs +++ b/taiga_halo2/src/taiga_api.rs @@ -24,7 +24,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; /// value is the fungible data of the resource /// nk is the nullifier key /// nonce guarantees the uniqueness of the resource computable fields -/// is_merkle_checked is true for normal resources, false for intent(ephemeral) resources +/// is_ephemeral is true for normal resources, false for intent(ephemeral) resources /// /// In practice, input resources are fetched and decrypted from blockchain storage. /// The create_input_resource API is only for test. @@ -34,7 +34,7 @@ pub fn create_input_resource( value: pallas::Base, quantity: u64, nk: pallas::Base, - is_merkle_checked: bool, + is_ephemeral: bool, ) -> Resource { let rng = OsRng; let nonce = Nullifier::random(rng); @@ -46,7 +46,7 @@ pub fn create_input_resource( quantity, nk, nonce, - is_merkle_checked, + is_ephemeral, rseed, ) } @@ -59,9 +59,9 @@ pub fn create_output_resource( quantity: u64, // The owner of output resource has the nullifer key and exposes the nullifier_key commitment to output creator. npk: pallas::Base, - is_merkle_checked: bool, + is_ephemeral: bool, ) -> Resource { - Resource::new_output_resource(logic, label, value, quantity, npk, is_merkle_checked) + Resource::new_output_resource(logic, label, value, quantity, npk, is_ephemeral) } /// Resource borsh serialization @@ -80,7 +80,7 @@ pub fn create_output_resource( /// | nonce | pallas::Base | 32 | /// | psi | pallas::Base | 32 | /// | rcm | pallas::Base | 32 | -/// | is_merkle_checked | u8 | 1 | +/// | is_ephemeral | u8 | 1 | #[cfg(feature = "borsh")] pub fn resource_serialize(resource: &Resource) -> std::io::Result> { let mut result = Vec::with_capacity(RESOURCE_SIZE); diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index 9f6963b9..c6bdddd8 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -90,7 +90,7 @@ impl Executable for TransparentPartialTransaction { fn get_anchors(&self) -> Vec { // TODO: We have easier way to check the anchor in transparent scenario, but keep consistent with sheilded right now. - // TODO: we can skip the root if the is_merkle_checked flag is false? + // TODO: we can skip the root if the is_ephemeral flag is false? self.compliances .iter() .map(|compliance| compliance.calculate_root()) From 1f1f55567c61ca661674e715bd87f17c64acd3a3 Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Wed, 29 Nov 2023 19:38:38 +0800 Subject: [PATCH 3/5] invert the is_ephemeral value --- taiga_halo2/benches/compliance_proof.rs | 4 ++-- taiga_halo2/benches/vp_proof.rs | 4 ++-- taiga_halo2/src/circuit/compliance_circuit.rs | 9 +++++---- .../src/circuit/vp_examples/cascade_intent.rs | 2 +- .../src/circuit/vp_examples/or_relation_intent.rs | 2 +- .../vp_examples/partial_fulfillment_intent/swap.rs | 2 +- taiga_halo2/src/circuit/vp_examples/token.rs | 12 ++++++------ taiga_halo2/src/resource.rs | 6 +++--- taiga_halo2/src/shielded_ptx.rs | 8 ++++---- taiga_halo2/src/taiga_api.rs | 2 +- taiga_halo2/src/transparent_ptx.rs | 2 +- 11 files changed, 27 insertions(+), 26 deletions(-) diff --git a/taiga_halo2/benches/compliance_proof.rs b/taiga_halo2/benches/compliance_proof.rs index 2e64c961..ecf3a1e0 100644 --- a/taiga_halo2/benches/compliance_proof.rs +++ b/taiga_halo2/benches/compliance_proof.rs @@ -37,7 +37,7 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: nk, - is_ephemeral: true, + is_ephemeral: false, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, @@ -59,7 +59,7 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: npk, - is_ephemeral: true, + is_ephemeral: false, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/benches/vp_proof.rs b/taiga_halo2/benches/vp_proof.rs index c7e9a25b..46637580 100644 --- a/taiga_halo2/benches/vp_proof.rs +++ b/taiga_halo2/benches/vp_proof.rs @@ -33,7 +33,7 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: nk, - is_ephemeral: true, + is_ephemeral: false, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, @@ -57,7 +57,7 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { value, quantity, nk_container: npk, - is_ephemeral: true, + is_ephemeral: false, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/src/circuit/compliance_circuit.rs b/taiga_halo2/src/circuit/compliance_circuit.rs index c102ca4c..390482f7 100644 --- a/taiga_halo2/src/circuit/compliance_circuit.rs +++ b/taiga_halo2/src/circuit/compliance_circuit.rs @@ -26,8 +26,8 @@ use halo2_gadgets::{ use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, plonk::{ - Advice, Circuit, Column, ConstraintSystem, Constraints, Error, Instance, Selector, - TableColumn, + Advice, Circuit, Column, ConstraintSystem, Constraints, Error, Expression, Instance, + Selector, TableColumn, }, poly::Rotation, }; @@ -128,12 +128,13 @@ impl Circuit for ComplianceCircuit { let is_ephemeral_input = meta.query_advice(advices[0], Rotation::cur()); let anchor = meta.query_advice(advices[1], Rotation::cur()); let root = meta.query_advice(advices[2], Rotation::cur()); + let constant_one = Expression::Constant(pallas::Base::one()); Constraints::with_selector( merkle_path_selector, [( - "is_ephemeral is false, or root = anchor", - is_ephemeral_input * (root - anchor), + "is_ephemeral is true, or root = anchor", + (constant_one - is_ephemeral_input) * (root - anchor), )], ) }); diff --git a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs index 4b90d84e..1a0700a7 100644 --- a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs @@ -163,7 +163,7 @@ pub fn create_intent_resource( 1u64, nk, nonce, - false, + true, rseed, ) } 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 ec4ada54..38f9a661 100644 --- a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs @@ -299,7 +299,7 @@ pub fn create_intent_resource( 1u64, nk, nonce, - false, + true, rseed, ) } diff --git a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs index d424677b..bd9fb8fa 100644 --- a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs +++ b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs @@ -108,7 +108,7 @@ impl Swap { 1u64, self.sell.resource().nk_container.get_nk().unwrap(), self.sell.resource().get_nf().unwrap(), - false, + true, rseed, ) } diff --git a/taiga_halo2/src/circuit/vp_examples/token.rs b/taiga_halo2/src/circuit/vp_examples/token.rs index e53046e7..2c605347 100644 --- a/taiga_halo2/src/circuit/vp_examples/token.rs +++ b/taiga_halo2/src/circuit/vp_examples/token.rs @@ -109,7 +109,7 @@ impl Token { self.quantity(), nk, nonce, - true, + false, rseed, ); @@ -132,7 +132,7 @@ impl Token { value, self.quantity(), npk, - true, + false, ); TokenResource { @@ -380,14 +380,14 @@ impl ValidityPredicateCircuit for TokenValidityPredicateCircuit { &owned_resource_id, &basic_variables.get_is_ephemeral_searchable_pairs(), )?; - let constant_one = assign_free_constant( - layouter.namespace(|| "one"), + let constant_zero = assign_free_constant( + layouter.namespace(|| "zero"), config.advices[0], - pallas::Base::one(), + pallas::Base::zero(), )?; layouter.assign_region( || "check is_ephemeral", - |mut region| region.constrain_equal(is_ephemeral.cell(), constant_one.cell()), + |mut region| region.constrain_equal(is_ephemeral.cell(), constant_zero.cell()), )?; // VP Commitment diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index 90a9c72d..60ee0cfc 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -104,7 +104,7 @@ pub struct Resource { pub psi: pallas::Base, /// rcm is the trapdoor of the resource commitment pub rcm: pallas::Base, - /// If the is_ephemeral flag is true, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. + /// If the is_ephemeral flag is false, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. pub is_ephemeral: bool, } @@ -221,7 +221,7 @@ impl Resource { nonce, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), - is_ephemeral: false, + is_ephemeral: true, } } @@ -579,7 +579,7 @@ pub mod tests { value: pallas::Base::random(&mut rng), quantity: rng.gen(), nk_container: random_nullifier_key(&mut rng), - is_ephemeral: true, + is_ephemeral: false, psi: rseed.get_psi(&nonce), rcm: rseed.get_rcm(&nonce), nonce, diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 1954058b..b238fd61 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -524,7 +524,7 @@ pub mod testing { let quantity = 5000u64; let nk = pallas::Base::random(&mut rng); let rseed = RandomSeed::random(&mut rng); - let is_ephemeral = true; + let is_ephemeral = false; Resource::new_input_resource( compressed_trivial_vp_vk, label, @@ -543,7 +543,7 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 5000u64; let npk = pallas::Base::random(&mut rng); - let is_ephemeral = true; + let is_ephemeral = false; Resource::new_output_resource( compressed_trivial_vp_vk, label, @@ -572,7 +572,7 @@ pub mod testing { let quantity = 10u64; let nk = pallas::Base::random(&mut rng); let rseed = RandomSeed::random(&mut rng); - let is_ephemeral = true; + let is_ephemeral = false; Resource::new_input_resource( compressed_trivial_vp_vk, label, @@ -589,7 +589,7 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 10u64; let npk = pallas::Base::random(&mut rng); - let is_ephemeral = true; + let is_ephemeral = false; Resource::new_output_resource( compressed_trivial_vp_vk, label, diff --git a/taiga_halo2/src/taiga_api.rs b/taiga_halo2/src/taiga_api.rs index 7a80c9e3..9e2a4e58 100644 --- a/taiga_halo2/src/taiga_api.rs +++ b/taiga_halo2/src/taiga_api.rs @@ -24,7 +24,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; /// value is the fungible data of the resource /// nk is the nullifier key /// nonce guarantees the uniqueness of the resource computable fields -/// is_ephemeral is true for normal resources, false for intent(ephemeral) resources +/// is_ephemeral is false for normal resources, true for intent(ephemeral) resources /// /// In practice, input resources are fetched and decrypted from blockchain storage. /// The create_input_resource API is only for test. diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index c6bdddd8..4ced2b3f 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -90,7 +90,7 @@ impl Executable for TransparentPartialTransaction { fn get_anchors(&self) -> Vec { // TODO: We have easier way to check the anchor in transparent scenario, but keep consistent with sheilded right now. - // TODO: we can skip the root if the is_ephemeral flag is false? + // TODO: we can skip the root if the is_ephemeral flag is true? self.compliances .iter() .map(|compliance| compliance.calculate_root()) From 77c79d35f5707fea2e450c2af0f030d4d6fac91d Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Mon, 4 Dec 2023 16:19:47 +0100 Subject: [PATCH 4/5] sync with RM: rseed, psi and rcm derivation --- taiga_halo2/benches/compliance_proof.rs | 12 +-- taiga_halo2/benches/vp_proof.rs | 12 +-- .../cascaded_partial_transactions.rs | 6 +- taiga_halo2/examples/tx_examples/token.rs | 2 +- .../tx_examples/token_swap_with_intent.rs | 2 +- taiga_halo2/src/circuit/integrity.rs | 23 +++- taiga_halo2/src/circuit/vp_circuit.rs | 16 +-- .../src/circuit/vp_examples/cascade_intent.rs | 3 +- .../circuit/vp_examples/or_relation_intent.rs | 3 +- .../partial_fulfillment_intent/swap.rs | 6 +- .../src/circuit/vp_examples/receiver_vp.rs | 34 ++++-- taiga_halo2/src/circuit/vp_examples/token.rs | 7 +- taiga_halo2/src/compliance.rs | 2 +- taiga_halo2/src/resource.rs | 101 ++++++------------ taiga_halo2/src/shielded_ptx.rs | 10 +- taiga_halo2/src/taiga_api.rs | 20 ++-- 16 files changed, 124 insertions(+), 135 deletions(-) diff --git a/taiga_halo2/benches/compliance_proof.rs b/taiga_halo2/benches/compliance_proof.rs index ecf3a1e0..654bb53d 100644 --- a/taiga_halo2/benches/compliance_proof.rs +++ b/taiga_halo2/benches/compliance_proof.rs @@ -15,7 +15,7 @@ use taiga_halo2::{ }, merkle_tree::MerklePath, nullifier::{Nullifier, NullifierKeyContainer}, - resource::{RandomSeed, Resource, ResourceKind}, + resource::{Resource, ResourceKind}, }; fn bench_compliance_proof(name: &str, c: &mut Criterion) { @@ -31,16 +31,15 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { }; let value = pallas::Base::random(&mut rng); let quantity: u64 = rng.gen(); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind, value, quantity, nk_container: nk, is_ephemeral: false, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } }; let mut output_resource = { @@ -53,16 +52,15 @@ fn bench_compliance_proof(name: &str, c: &mut Criterion) { }; let value = pallas::Base::random(&mut rng); let quantity: u64 = rng.gen(); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind, value, quantity, nk_container: npk, is_ephemeral: false, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } }; let input_merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); diff --git a/taiga_halo2/benches/vp_proof.rs b/taiga_halo2/benches/vp_proof.rs index 46637580..cf952dd7 100644 --- a/taiga_halo2/benches/vp_proof.rs +++ b/taiga_halo2/benches/vp_proof.rs @@ -10,7 +10,7 @@ use taiga_halo2::{ constant::{NUM_RESOURCE, SETUP_PARAMS_MAP, VP_CIRCUIT_PARAMS_SIZE}, nullifier::{Nullifier, NullifierKeyContainer}, proof::Proof, - resource::{RandomSeed, Resource, ResourceKind}, + resource::{Resource, ResourceKind}, }; fn bench_vp_proof(name: &str, c: &mut Criterion) { @@ -27,16 +27,15 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { }; let value = pallas::Base::random(&mut rng); let quantity: u64 = rng.gen(); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind, value, quantity, nk_container: nk, is_ephemeral: false, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } }); let output_resources = input_resources @@ -51,16 +50,15 @@ fn bench_vp_proof(name: &str, c: &mut Criterion) { }; let value = pallas::Base::random(&mut rng); let quantity: u64 = rng.gen(); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind, value, quantity, nk_container: npk, is_ephemeral: false, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } }) .collect::>(); diff --git a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs index f08c0911..b93879d3 100644 --- a/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs +++ b/taiga_halo2/examples/tx_examples/cascaded_partial_transactions.rs @@ -31,7 +31,7 @@ pub fn create_transaction(mut rng: R) -> Transaction { input_token_1.create_random_input_token_resource(&mut rng, alice_nk, &alice_auth); let output_token_1 = Token::new("btc".to_string(), 1u64); let mut output_resource_1 = - output_token_1.create_random_output_token_resource(bob_npk, &bob_auth); + output_token_1.create_random_output_token_resource(&mut rng, bob_npk, &bob_auth); let input_token_2 = Token::new("eth".to_string(), 2u64); let input_resource_2 = input_token_2.create_random_input_token_resource(&mut rng, alice_nk, &alice_auth); @@ -43,10 +43,10 @@ pub fn create_transaction(mut rng: R) -> Transaction { create_intent_resource(&mut rng, input_resource_3.commitment().inner(), alice_nk); let output_token_2 = Token::new("eth".to_string(), 2u64); let mut output_resource_2 = - output_token_2.create_random_output_token_resource(bob_npk, &bob_auth); + output_token_2.create_random_output_token_resource(&mut rng, bob_npk, &bob_auth); let output_token_3 = Token::new("xan".to_string(), 3u64); let mut output_resource_3 = - output_token_3.create_random_output_token_resource(bob_npk, &bob_auth); + output_token_3.create_random_output_token_resource(&mut rng, bob_npk, &bob_auth); let merkle_path = MerklePath::random(&mut rng, TAIGA_COMMITMENT_TREE_DEPTH); diff --git a/taiga_halo2/examples/tx_examples/token.rs b/taiga_halo2/examples/tx_examples/token.rs index 1202d27f..68a829ac 100644 --- a/taiga_halo2/examples/tx_examples/token.rs +++ b/taiga_halo2/examples/tx_examples/token.rs @@ -34,7 +34,7 @@ pub fn create_token_swap_ptx( // output resource let output_auth = TokenAuthorization::new(output_auth_pk, *COMPRESSED_TOKEN_AUTH_VK); let mut output_resource = - output_token.create_random_output_token_resource(output_npk, &output_auth); + output_token.create_random_output_token_resource(&mut rng, output_npk, &output_auth); // padding the zero resources let padding_input_resource = Resource::random_padding_resource(&mut rng); 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 8ee10ef7..3cbd3b88 100644 --- a/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs +++ b/taiga_halo2/examples/tx_examples/token_swap_with_intent.rs @@ -163,7 +163,7 @@ pub fn consume_token_intent_ptx( let output_auth = TokenAuthorization::new(output_auth_pk, *COMPRESSED_TOKEN_AUTH_VK); let output_npk = NullifierKeyContainer::from_key(input_nk).get_npk(); let mut output_resource = - output_token.create_random_output_token_resource(output_npk, &output_auth); + output_token.create_random_output_token_resource(&mut rng, output_npk, &output_auth); // padding the zero resources let padding_input_resource = Resource::random_padding_resource(&mut rng); diff --git a/taiga_halo2/src/circuit/integrity.rs b/taiga_halo2/src/circuit/integrity.rs index f9410770..3aa1a9b6 100644 --- a/taiga_halo2/src/circuit/integrity.rs +++ b/taiga_halo2/src/circuit/integrity.rs @@ -104,6 +104,15 @@ pub fn check_input_resource( Value::known(input_resource.nonce.inner()), )?; + // Witness rseed + let rseed = assign_free_advice( + layouter.namespace(|| "witness rseed"), + advices[0], + Value::known(input_resource.rseed), + )?; + + // We don't need the constraints on psi and rcm derivation for input resource. + // If the psi and rcm are not correct, the existence checking would fail. // Witness psi let psi = assign_free_advice( layouter.namespace(|| "witness psi_input"), @@ -162,8 +171,7 @@ pub fn check_input_resource( value, nonce, npk, - psi, - rcm, + rseed, }; Ok(InputResourceVariables { @@ -218,6 +226,14 @@ pub fn check_output_resource( output_resource.quantity, )?; + // Witness rseed + let rseed = assign_free_advice( + layouter.namespace(|| "witness rseed"), + advices[0], + Value::known(output_resource.rseed), + )?; + + // TODO: constrain on psi and rcm derivation // Witness rcm let rcm = assign_free_advice( layouter.namespace(|| "witness rcm"), @@ -266,8 +282,7 @@ pub fn check_output_resource( value, nonce: old_nf, npk, - psi, - rcm, + rseed, }; Ok(OutputResourceVariables { diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index 7f3b5f88..e6769def 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -575,8 +575,7 @@ pub struct ResourceVariables { pub value: AssignedCell, pub nonce: AssignedCell, pub npk: AssignedCell, - pub psi: AssignedCell, - pub rcm: AssignedCell, + pub rseed: AssignedCell, } // Variables in the input resource @@ -708,17 +707,10 @@ impl BasicValidityPredicateVariables { ) } - pub fn get_psi_searchable_pairs(&self) -> [ResourceSearchableVariablePair; NUM_RESOURCE * 2] { + pub fn get_rseed_searchable_pairs(&self) -> [ResourceSearchableVariablePair; NUM_RESOURCE * 2] { self.get_variable_searchable_pairs( - |variables| variables.resource_variables.psi.clone(), - |variables| variables.resource_variables.psi.clone(), - ) - } - - pub fn get_rcm_searchable_pairs(&self) -> [ResourceSearchableVariablePair; NUM_RESOURCE * 2] { - self.get_variable_searchable_pairs( - |variables| variables.resource_variables.rcm.clone(), - |variables| variables.resource_variables.rcm.clone(), + |variables| variables.resource_variables.rseed.clone(), + |variables| variables.resource_variables.rseed.clone(), ) } } diff --git a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs index 1a0700a7..d0f98e03 100644 --- a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs @@ -24,6 +24,7 @@ use crate::{ vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; +use halo2_proofs::arithmetic::Field; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, plonk::{keygen_pk, keygen_vk, Circuit, ConstraintSystem, Error}, @@ -154,7 +155,7 @@ pub fn create_intent_resource( nk: pallas::Base, ) -> Resource { let label = CascadeIntentValidityPredicateCircuit::encode_label(cascade_resource_cm); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let nonce = Nullifier::random(&mut rng); Resource::new_input_resource( *COMPRESSED_CASCADE_INTENT_VK, 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 38f9a661..11dd25db 100644 --- a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs @@ -25,6 +25,7 @@ use crate::{ vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; +use halo2_proofs::arithmetic::Field; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, plonk::{keygen_pk, keygen_vk, Circuit, ConstraintSystem, Error}, @@ -290,7 +291,7 @@ pub fn create_intent_resource( receiver_npk, receiver_value, ); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let nonce = Nullifier::random(&mut rng); Resource::new_input_resource( *COMPRESSED_OR_RELATION_INTENT_VK, diff --git a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs index bd9fb8fa..549cb166 100644 --- a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs +++ b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent/swap.rs @@ -5,7 +5,7 @@ use crate::{ vp_examples::token::{Token, TokenAuthorization, TokenResource, TOKEN_VK}, }, constant::NUM_RESOURCE, - resource::{RandomSeed, Resource}, + resource::Resource, utils::poseidon_hash_n, }; use halo2_proofs::arithmetic::Field; @@ -56,6 +56,7 @@ impl Swap { assert_eq!(offer.quantity() % ratio, 0); let offer_resource = offer.create_random_output_token_resource( + &mut rng, self.sell.resource().nk_container.get_npk(), &self.auth, ); @@ -71,6 +72,7 @@ impl Swap { ); *returned_token .create_random_output_token_resource( + &mut rng, self.sell.resource().nk_container.get_npk(), &self.auth, ) @@ -99,7 +101,7 @@ impl Swap { } pub fn create_intent_resource(&self, mut rng: R) -> Resource { - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource::new_input_resource( *COMPRESSED_PARTIAL_FULFILLMENT_INTENT_VK, diff --git a/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs b/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs index 433e6d74..f54e61b8 100644 --- a/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs +++ b/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs @@ -172,21 +172,30 @@ impl ValidityPredicateCircuit for ReceiverValidityPredicateCircuit { &basic_variables.get_npk_searchable_pairs(), )?; - let psi = get_owned_resource_variable( + let is_ephemeral = get_owned_resource_variable( config.get_owned_resource_variable_config, - layouter.namespace(|| "get owned resource psi"), + layouter.namespace(|| "get owned resource is_ephemeral"), &owned_resource_id, - &basic_variables.get_psi_searchable_pairs(), + &basic_variables.get_is_ephemeral_searchable_pairs(), )?; - let rcm = get_owned_resource_variable( + let rseed = get_owned_resource_variable( config.get_owned_resource_variable_config, - layouter.namespace(|| "get owned resource psi"), + layouter.namespace(|| "get owned resource rseed"), &owned_resource_id, - &basic_variables.get_rcm_searchable_pairs(), + &basic_variables.get_rseed_searchable_pairs(), )?; - let mut message = vec![logic, label, value, quantity, nonce, npk, psi, rcm]; + let mut message = vec![ + logic, + label, + value, + quantity, + nonce, + npk, + is_ephemeral, + rseed, + ]; let add_chip = AddChip::::construct(config.add_config.clone(), ()); @@ -249,8 +258,8 @@ impl ValidityPredicateCircuit for ReceiverValidityPredicateCircuit { pallas::Base::from(target_resource.quantity), target_resource.nonce.inner(), target_resource.get_npk(), - target_resource.psi, - target_resource.rcm, + pallas::Base::from(target_resource.is_ephemeral as u64), + target_resource.rseed, ]; let plaintext = ResourcePlaintext::padding(&message); let key = SecretKey::from_dh_exchange(&self.rcv_pk, &mod_r_p(self.sk)); @@ -332,6 +341,9 @@ fn test_halo2_receiver_vp_circuit() { ); assert_eq!(de_cipher[4], circuit.output_resources[0].nonce.inner()); assert_eq!(de_cipher[5], circuit.output_resources[0].get_npk()); - assert_eq!(de_cipher[6], circuit.output_resources[0].get_psi()); - assert_eq!(de_cipher[7], circuit.output_resources[0].get_rcm()); + assert_eq!( + de_cipher[6], + pallas::Base::from(circuit.output_resources[0].is_ephemeral) + ); + assert_eq!(de_cipher[7], circuit.output_resources[0].rseed); } diff --git a/taiga_halo2/src/circuit/vp_examples/token.rs b/taiga_halo2/src/circuit/vp_examples/token.rs index 2c605347..8dfc6683 100644 --- a/taiga_halo2/src/circuit/vp_examples/token.rs +++ b/taiga_halo2/src/circuit/vp_examples/token.rs @@ -100,7 +100,7 @@ impl Token { ) -> TokenResource { let label = self.encode_name(); let value = auth.to_value(); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let nonce = Nullifier::random(&mut rng); let resource = Resource::new_input_resource( *COMPRESSED_TOKEN_VK, @@ -119,13 +119,15 @@ impl Token { } } - pub fn create_random_output_token_resource( + pub fn create_random_output_token_resource( &self, + mut rng: R, npk: pallas::Base, auth: &TokenAuthorization, ) -> TokenResource { let label = self.encode_name(); let value = auth.to_value(); + let rseed = pallas::Base::random(&mut rng); let resource = Resource::new_output_resource( *COMPRESSED_TOKEN_VK, label, @@ -133,6 +135,7 @@ impl Token { self.quantity(), npk, false, + rseed, ); TokenResource { diff --git a/taiga_halo2/src/compliance.rs b/taiga_halo2/src/compliance.rs index 8ddf36dc..585470e8 100644 --- a/taiga_halo2/src/compliance.rs +++ b/taiga_halo2/src/compliance.rs @@ -138,7 +138,7 @@ impl ComplianceInfo { None => input_resource.calculate_root(&input_merkle_path), }; - output_resource.set_nonce(&input_resource, &mut rng); + output_resource.set_nonce(&input_resource); Self { input_resource, diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index 60ee0cfc..84041199 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -100,12 +100,10 @@ pub struct Resource { pub nk_container: NullifierKeyContainer, /// nonce guarantees the uniqueness of the resource computable fields pub nonce: Nullifier, - /// psi is to derive the nullifier - pub psi: pallas::Base, - /// rcm is the trapdoor of the resource commitment - pub rcm: pallas::Base, /// If the is_ephemeral flag is false, the merkle path authorization(membership) of input resource will be checked in ComplianceProof. pub is_ephemeral: bool, + /// randomness seed used to derive whatever randomness needed (e.g., the resource commitment randomness and nullifier derivation randomness) + pub rseed: pallas::Base, } /// The parameters in the ResourceKind are used to derive resource kind. @@ -142,7 +140,7 @@ impl Resource { nk: pallas::Base, nonce: Nullifier, is_ephemeral: bool, - rseed: RandomSeed, + rseed: pallas::Base, ) -> Self { let kind = ResourceKind::new(logic, label); Self { @@ -151,9 +149,8 @@ impl Resource { quantity, nk_container: NullifierKeyContainer::Key(nk), is_ephemeral, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } } @@ -166,6 +163,7 @@ impl Resource { quantity: u64, npk: pallas::Base, is_ephemeral: bool, + rseed: pallas::Base, ) -> Self { let kind = ResourceKind::new(logic, label); Self { @@ -174,8 +172,7 @@ impl Resource { quantity, nk_container: NullifierKeyContainer::PublicKey(npk), is_ephemeral, - psi: pallas::Base::default(), - rcm: pallas::Base::default(), + rseed, nonce: Nullifier::default(), } } @@ -189,8 +186,7 @@ impl Resource { nk_container: NullifierKeyContainer, nonce: Nullifier, is_ephemeral: bool, - psi: pallas::Base, - rcm: pallas::Base, + rseed: pallas::Base, ) -> Self { let kind = ResourceKind::new(logic, label); Self { @@ -199,9 +195,8 @@ impl Resource { quantity, nk_container, is_ephemeral, - psi, - rcm, nonce, + rseed, } } @@ -212,15 +207,14 @@ impl Resource { let value = pallas::Base::random(&mut rng); let nonce = Nullifier::from(pallas::Base::random(&mut rng)); let nk = NullifierKeyContainer::from_key(pallas::Base::random(&mut rng)); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind, value, quantity: 0, nk_container: nk, nonce, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), + rseed, is_ephemeral: true, } } @@ -238,9 +232,9 @@ impl Resource { self.value, self.get_npk(), self.nonce.inner(), - self.psi, + self.get_psi(), compose_is_ephemeral_quantity, - self.rcm, + self.get_rcm(), ]); ResourceCommitment(ret) } @@ -249,7 +243,7 @@ impl Resource { Nullifier::derive( &self.nk_container, &self.nonce.inner(), - &self.psi, + &self.get_psi(), &self.commitment(), ) } @@ -274,12 +268,14 @@ impl Resource { self.kind.label } + // psi is the randomness used to derive the nullifier pub fn get_psi(&self) -> pallas::Base { - self.psi + poseidon_hash_n([self.rseed, self.nonce.inner()]) } + // rcm is the randomness of resource commitment pub fn get_rcm(&self) -> pallas::Base { - self.rcm + poseidon_hash_n([self.rseed, self.nonce.inner()]) } pub fn calculate_root(&self, path: &MerklePath) -> Anchor { @@ -287,12 +283,8 @@ impl Resource { path.root(cm_node) } - pub fn set_nonce(&mut self, input_resource: &Resource, mut rng: R) { - let rseed = RandomSeed::random(&mut rng); - + pub fn set_nonce(&mut self, input_resource: &Resource) { self.nonce = input_resource.get_nf().unwrap(); - self.psi = rseed.get_psi(&self.nonce); - self.rcm = rseed.get_rcm(&self.nonce); } } @@ -321,12 +313,10 @@ impl BorshSerialize for Resource { }?; // Write nonce writer.write_all(&self.nonce.to_bytes())?; - // Write psi - writer.write_all(&self.psi.to_repr())?; - // Write rcm - writer.write_all(&self.rcm.to_repr())?; // Write is_ephemeral writer.write_u8(if self.is_ephemeral { 1 } else { 0 })?; + // Write rseed + writer.write_all(&self.rseed.to_repr())?; Ok(()) } @@ -372,21 +362,18 @@ impl BorshDeserialize for Resource { reader.read_exact(&mut nonce_bytes)?; let nonce = Option::from(Nullifier::from_bytes(nonce_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "nonce not in field"))?; - // Read psi - let mut psi_bytes = [0u8; 32]; - reader.read_exact(&mut psi_bytes)?; - let psi = Option::from(pallas::Base::from_repr(psi_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "psi not in field"))?; - // Read rcm - let mut rcm_bytes = [0u8; 32]; - reader.read_exact(&mut rcm_bytes)?; - let rcm = Option::from(pallas::Base::from_repr(rcm_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "rcm not in field"))?; + // Read is_ephemeral let mut is_ephemeral_byte = [0u8; 1]; reader.read_exact(&mut is_ephemeral_byte)?; let is_ephemeral_byte = is_ephemeral_byte[0]; let is_ephemeral = is_ephemeral_byte == 0x01; + + // Read rseed + let mut rseed_bytes = [0u8; 32]; + reader.read_exact(&mut rseed_bytes)?; + let rseed = Option::from(pallas::Base::from_repr(rseed_bytes)) + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "rseed not in field"))?; // Construct resource Ok(Resource::from_full( logic, @@ -396,8 +383,7 @@ impl BorshDeserialize for Resource { nk_container, nonce, is_ephemeral, - psi, - rcm, + rseed, )) } } @@ -434,30 +420,6 @@ impl RandomSeed { Self(rseed) } - pub fn get_psi(&self, nonce: &Nullifier) -> pallas::Base { - let mut h = Blake2bParams::new() - .hash_length(64) - .personal(PRF_EXPAND_PERSONALIZATION) - .to_state(); - h.update(&[PRF_EXPAND_PSI]); - h.update(&self.0); - h.update(&nonce.to_bytes()); - let psi_bytes = *h.finalize().as_array(); - pallas::Base::from_uniform_bytes(&psi_bytes) - } - - pub fn get_rcm(&self, nonce: &Nullifier) -> pallas::Base { - let mut h = Blake2bParams::new() - .hash_length(64) - .personal(PRF_EXPAND_PERSONALIZATION) - .to_state(); - h.update(&[PRF_EXPAND_RCM]); - h.update(&self.0); - h.update(&nonce.to_bytes()); - let rcm_bytes = *h.finalize().as_array(); - pallas::Base::from_uniform_bytes(&rcm_bytes) - } - pub fn get_random_padding(&self, padding_len: usize) -> Vec { (0..padding_len) .map(|i| { @@ -559,7 +521,7 @@ impl ResourceValidityPredicates { #[cfg(test)] pub mod tests { - use super::{RandomSeed, Resource, ResourceKind}; + use super::{Resource, ResourceKind}; use crate::nullifier::tests::*; use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; @@ -573,16 +535,15 @@ pub mod tests { pub fn random_resource(mut rng: R) -> Resource { let nonce = random_nullifier(&mut rng); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource { kind: random_kind(&mut rng), value: pallas::Base::random(&mut rng), quantity: rng.gen(), nk_container: random_nullifier_key(&mut rng), is_ephemeral: false, - psi: rseed.get_psi(&nonce), - rcm: rseed.get_rcm(&nonce), nonce, + rseed, } } diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index b238fd61..661157b7 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -495,7 +495,7 @@ pub mod testing { constant::TAIGA_COMMITMENT_TREE_DEPTH, merkle_tree::MerklePath, nullifier::Nullifier, - resource::{RandomSeed, Resource, ResourceValidityPredicates}, + resource::{Resource, ResourceValidityPredicates}, shielded_ptx::ShieldedPartialTransaction, utils::poseidon_hash, }; @@ -523,7 +523,7 @@ pub mod testing { let nonce = Nullifier::from(pallas::Base::random(&mut rng)); let quantity = 5000u64; let nk = pallas::Base::random(&mut rng); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let is_ephemeral = false; Resource::new_input_resource( compressed_trivial_vp_vk, @@ -543,6 +543,7 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 5000u64; let npk = pallas::Base::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let is_ephemeral = false; Resource::new_output_resource( compressed_trivial_vp_vk, @@ -551,6 +552,7 @@ pub mod testing { quantity, npk, is_ephemeral, + rseed, ) }; @@ -571,7 +573,7 @@ pub mod testing { let nonce = Nullifier::from(pallas::Base::random(&mut rng)); let quantity = 10u64; let nk = pallas::Base::random(&mut rng); - let rseed = RandomSeed::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let is_ephemeral = false; Resource::new_input_resource( compressed_trivial_vp_vk, @@ -589,6 +591,7 @@ pub mod testing { let value = pallas::Base::zero(); let quantity = 10u64; let npk = pallas::Base::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); let is_ephemeral = false; Resource::new_output_resource( compressed_trivial_vp_vk, @@ -597,6 +600,7 @@ pub mod testing { quantity, npk, is_ephemeral, + rseed, ) }; diff --git a/taiga_halo2/src/taiga_api.rs b/taiga_halo2/src/taiga_api.rs index 9e2a4e58..3ffe4243 100644 --- a/taiga_halo2/src/taiga_api.rs +++ b/taiga_halo2/src/taiga_api.rs @@ -6,14 +6,15 @@ use crate::{ use crate::{ error::TransactionError, nullifier::Nullifier, - resource::{RandomSeed, Resource}, + resource::Resource, shielded_ptx::ShieldedPartialTransaction, transaction::{ShieldedPartialTxBundle, Transaction, TransparentPartialTxBundle}, }; +use ff::Field; use pasta_curves::pallas; use rand::rngs::OsRng; -pub const RESOURCE_SIZE: usize = 234; +pub const RESOURCE_SIZE: usize = 202; #[cfg(feature = "borsh")] use borsh::{BorshDeserialize, BorshSerialize}; @@ -36,9 +37,9 @@ pub fn create_input_resource( nk: pallas::Base, is_ephemeral: bool, ) -> Resource { - let rng = OsRng; - let nonce = Nullifier::random(rng); - let rseed = RandomSeed::random(rng); + let mut rng = OsRng; + let nonce = Nullifier::random(&mut rng); + let rseed = pallas::Base::random(&mut rng); Resource::new_input_resource( logic, label, @@ -61,12 +62,14 @@ pub fn create_output_resource( npk: pallas::Base, is_ephemeral: bool, ) -> Resource { - Resource::new_output_resource(logic, label, value, quantity, npk, is_ephemeral) + let mut rng = OsRng; + let rseed = pallas::Base::random(&mut rng); + Resource::new_output_resource(logic, label, value, quantity, npk, is_ephemeral, rseed) } /// Resource borsh serialization /// -/// Resource size: 234 bytes +/// Resource size: 202 bytes /// /// Resource layout: /// | Parameters | type |size(bytes)| @@ -78,9 +81,8 @@ pub fn create_output_resource( /// | nk_container type | u8 | 1 | /// | npk | pallas::Base | 32 | /// | nonce | pallas::Base | 32 | -/// | psi | pallas::Base | 32 | -/// | rcm | pallas::Base | 32 | /// | is_ephemeral | u8 | 1 | +/// | rseed | pallas::Base | 32 | #[cfg(feature = "borsh")] pub fn resource_serialize(resource: &Resource) -> std::io::Result> { let mut result = Vec::with_capacity(RESOURCE_SIZE); From dbb32ff703de0dfe101ed018080af0c6a5b25f05 Mon Sep 17 00:00:00 2001 From: Song Xuyang Date: Mon, 4 Dec 2023 16:49:47 +0100 Subject: [PATCH 5/5] constrain the derivation of psi and rcm --- taiga_halo2/src/circuit/integrity.rs | 51 +++++++++++++++++++++++----- taiga_halo2/src/constant.rs | 5 +++ taiga_halo2/src/resource.rs | 19 ++++++++--- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/taiga_halo2/src/circuit/integrity.rs b/taiga_halo2/src/circuit/integrity.rs index 3aa1a9b6..075d4fe7 100644 --- a/taiga_halo2/src/circuit/integrity.rs +++ b/taiga_halo2/src/circuit/integrity.rs @@ -4,7 +4,10 @@ use crate::circuit::{ resource_commitment::{resource_commit, ResourceCommitChip}, vp_circuit::{InputResourceVariables, OutputResourceVariables, ResourceVariables}, }; -use crate::constant::{TaigaFixedBases, TaigaFixedBasesFull, POSEIDON_TO_CURVE_INPUT_LEN}; +use crate::constant::{ + TaigaFixedBases, TaigaFixedBasesFull, POSEIDON_TO_CURVE_INPUT_LEN, + PRF_EXPAND_PERSONALIZATION_TO_FIELD, PRF_EXPAND_PSI, PRF_EXPAND_RCM, +}; use crate::resource::Resource; use crate::utils::poseidon_to_curve; use halo2_gadgets::{ @@ -233,19 +236,49 @@ pub fn check_output_resource( Value::known(output_resource.rseed), )?; - // TODO: constrain on psi and rcm derivation // Witness rcm - let rcm = assign_free_advice( - layouter.namespace(|| "witness rcm"), + let prf_expand_personalization = assign_free_constant( + layouter.namespace(|| "constant PRF_EXPAND_PERSONALIZATION_TO_FIELD"), advices[0], - Value::known(output_resource.get_rcm()), + *PRF_EXPAND_PERSONALIZATION_TO_FIELD, + )?; + let rcm_message = { + let prf_expand_rcm = assign_free_constant( + layouter.namespace(|| "constant PRF_EXPAND_RCM"), + advices[0], + pallas::Base::from(PRF_EXPAND_RCM as u64), + )?; + [ + prf_expand_personalization.clone(), + prf_expand_rcm, + rseed.clone(), + old_nf.clone(), + ] + }; + let rcm = poseidon_hash_gadget( + resource_commit_chip.get_poseidon_config(), + layouter.namespace(|| "derive the rcm"), + rcm_message, )?; // Witness psi - let psi = assign_free_advice( - layouter.namespace(|| "witness psi_output"), - advices[0], - Value::known(output_resource.get_psi()), + let psi_message = { + let prf_expand_psi = assign_free_constant( + layouter.namespace(|| "constant PRF_EXPAND_PSI"), + advices[0], + pallas::Base::from(PRF_EXPAND_PSI as u64), + )?; + [ + prf_expand_personalization, + prf_expand_psi, + rseed.clone(), + old_nf.clone(), + ] + }; + let psi = poseidon_hash_gadget( + resource_commit_chip.get_poseidon_config(), + layouter.namespace(|| "derive the psi"), + psi_message, )?; // Witness is_ephemeral diff --git a/taiga_halo2/src/constant.rs b/taiga_halo2/src/constant.rs index eb74f732..193e3ebf 100644 --- a/taiga_halo2/src/constant.rs +++ b/taiga_halo2/src/constant.rs @@ -27,6 +27,11 @@ pub const TRANSACTION_BINDING_HASH_PERSONALIZATION: &[u8; 16] = b"TxBindingSigHa pub const VP_COMMITMENT_PERSONALIZATION: &[u8; 8] = b"VPCommit"; pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Taiga_ExpandSeed"; +lazy_static! { + pub static ref PRF_EXPAND_PERSONALIZATION_TO_FIELD: pallas::Base = + to_field_elements(PRF_EXPAND_PERSONALIZATION)[0]; +} + pub const PRF_EXPAND_PSI: u8 = 0; pub const PRF_EXPAND_RCM: u8 = 1; pub const PRF_EXPAND_PUBLIC_INPUT_PADDING: u8 = 2; diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index 84041199..8c67dd27 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -4,8 +4,9 @@ use crate::{ vp_examples::{TrivialValidityPredicateCircuit, COMPRESSED_TRIVIAL_VP_VK}, }, constant::{ - NUM_RESOURCE, POSEIDON_TO_CURVE_INPUT_LEN, PRF_EXPAND_PERSONALIZATION, PRF_EXPAND_PSI, - PRF_EXPAND_PUBLIC_INPUT_PADDING, PRF_EXPAND_RCM, PRF_EXPAND_VCM_R, + NUM_RESOURCE, POSEIDON_TO_CURVE_INPUT_LEN, PRF_EXPAND_PERSONALIZATION, + PRF_EXPAND_PERSONALIZATION_TO_FIELD, PRF_EXPAND_PSI, PRF_EXPAND_PUBLIC_INPUT_PADDING, + PRF_EXPAND_RCM, PRF_EXPAND_VCM_R, }, merkle_tree::{Anchor, MerklePath, Node}, nullifier::{Nullifier, NullifierKeyContainer}, @@ -270,12 +271,22 @@ impl Resource { // psi is the randomness used to derive the nullifier pub fn get_psi(&self) -> pallas::Base { - poseidon_hash_n([self.rseed, self.nonce.inner()]) + poseidon_hash_n([ + *PRF_EXPAND_PERSONALIZATION_TO_FIELD, + pallas::Base::from(PRF_EXPAND_PSI as u64), + self.rseed, + self.nonce.inner(), + ]) } // rcm is the randomness of resource commitment pub fn get_rcm(&self) -> pallas::Base { - poseidon_hash_n([self.rseed, self.nonce.inner()]) + poseidon_hash_n([ + *PRF_EXPAND_PERSONALIZATION_TO_FIELD, + pallas::Base::from(PRF_EXPAND_RCM as u64), + self.rseed, + self.nonce.inner(), + ]) } pub fn calculate_root(&self, path: &MerklePath) -> Anchor {