diff --git a/arm/elfs/compliance-guest.bin b/arm/elfs/compliance-guest.bin index edec4430..6355a900 100644 Binary files a/arm/elfs/compliance-guest.bin and b/arm/elfs/compliance-guest.bin differ diff --git a/arm/elfs/trivial-logic-guest.bin b/arm/elfs/trivial-logic-guest.bin index 87446363..3deba943 100644 Binary files a/arm/elfs/trivial-logic-guest.bin and b/arm/elfs/trivial-logic-guest.bin differ diff --git a/arm/src/action.rs b/arm/src/action.rs index 8628e276..bbcb4e8f 100644 --- a/arm/src/action.rs +++ b/arm/src/action.rs @@ -3,7 +3,7 @@ use crate::{ compliance::{ComplianceInstance, ComplianceWitness}, compliance_unit::ComplianceUnit, delta_proof::DeltaWitness, - logic_proof::{LogicProof, LogicProver}, + logic_proof::{LogicProver, LogicVerifier, LogicVerifierInputs}, merkle_path::COMMITMENT_TREE_DEPTH, nullifier_key::NullifierKey, resource::Resource, @@ -19,17 +19,14 @@ use serde::{Deserialize, Serialize}; #[cfg_attr(feature = "nif", module = "Anoma.Arm.Action")] pub struct Action { pub compliance_units: Vec, - pub logic_verifier_inputs: Vec, + pub logic_verifier_inputs: Vec, } impl Action { - pub fn new( - compliance_units: Vec, - logic_verifier_inputs: Vec, - ) -> Self { + pub fn new(compliance_units: Vec, logic_verifiers: Vec) -> Self { Action { compliance_units, - logic_verifier_inputs, + logic_verifier_inputs: logic_verifiers.into_iter().map(|lv| lv.into()).collect(), } } @@ -37,11 +34,11 @@ impl Action { &self.compliance_units } - pub fn get_logic_verifier_inputs(&self) -> &Vec { + pub fn get_logic_verifier_inputs(&self) -> &Vec { &self.logic_verifier_inputs } - pub fn verify(&self) -> bool { + pub fn verify(self) -> bool { for unit in &self.compliance_units { if !unit.verify() { return false; @@ -76,22 +73,20 @@ impl Action { let action_tree = MerkleTree::from(tags.clone()); let root = action_tree.root(); - for proof in &self.logic_verifier_inputs { - let instance = proof.get_instance(); - - if root != instance.root { - return false; - } + for input in self.logic_verifier_inputs { + if let Some(index) = tags.iter().position(|tag| *tag == input.tag) { + if input.verifying_key != logics[index] { + // The verifying_key doesn't match the resource logic + return false; + } - if let Some(index) = tags.iter().position(|tag| *tag == instance.tag) { - if proof.verifying_key != logics[index] { + let is_comsumed = index % 2 == 0; + let verifier = input.to_logic_verifier(is_comsumed, root.clone()); + if !verifier.verify() { return false; } } else { - return false; - } - - if !proof.verify() { + // Tag not found return false; } } @@ -159,7 +154,7 @@ pub fn create_an_action(nonce: u8) -> (Action, DeltaWitness) { let logic_verifier_inputs = vec![consumed_logic_proof, created_logic_proof]; let action = Action::new(compliance_units, logic_verifier_inputs); - assert!(action.verify()); + assert!(action.clone().verify()); let delta_witness = DeltaWitness::from_bytes_vec(&[compliance_witness.rcv]); (action, delta_witness) diff --git a/arm/src/constants.rs b/arm/src/constants.rs index 80f911b0..7dd602ef 100644 --- a/arm/src/constants.rs +++ b/arm/src/constants.rs @@ -10,11 +10,11 @@ pub const PADDING_LOGIC_PK: &[u8] = include_bytes!("../elfs/trivial-logic-guest. lazy_static! { // compliance verification key / compliance image id pub static ref COMPLIANCE_VK: Digest = - Digest::from_hex("e04fd74c5f4ed1fc3ccf4412c358927907eec18891c87f157a4b0eede2e01adc") + Digest::from_hex("2c10d71e919b8b6359bfc167294c9994c1699e3eeb851d4b7775edb67b54a327") .unwrap(); // compliance verification key / compliance image id pub static ref PADDING_LOGIC_VK: Digest = - Digest::from_hex("751068c8a7bf034fefac9ba4adb745ecb5a1345e40345b8f0a4bef380f06fbe2") + Digest::from_hex("f8047dc2cf6cbe45137a588a3f019814218e7d7199b1b86a57b51c310e04fae9") .unwrap(); } diff --git a/arm/src/encryption.rs b/arm/src/encryption.rs index d20e3be4..23c99927 100644 --- a/arm/src/encryption.rs +++ b/arm/src/encryption.rs @@ -1,3 +1,4 @@ +use crate::utils::{bytes_to_words, words_to_bytes}; use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit}; use k256::{ elliptic_curve::{group::GroupEncoding, Field}, @@ -28,12 +29,26 @@ impl SecretKey { pub struct Ciphertext(Vec); impl Ciphertext { - pub fn new(cipher: Vec) -> Self { + pub fn from_bytes(cipher: Vec) -> Self { Ciphertext(cipher) } - pub fn inner(&self) -> Vec { - self.0.clone() + pub fn from_words(words: &[u32]) -> Self { + Ciphertext(words_to_bytes(words).to_vec()) + } + + pub fn inner(&self) -> &[u8] { + &self.0 + } + + pub fn as_words(&self) -> Vec { + let mut padded = self.inner().to_vec(); + let len = self.inner().len(); + let rem = len % 4; + if rem != 0 { + padded.resize(len + (4 - rem), 0); + } + bytes_to_words(&padded) } pub fn encrypt( @@ -63,7 +78,7 @@ impl Ciphertext { return Err(aes_gcm::Error); } let cipher: InnerCiphert = - bincode::deserialize(&self.inner()).expect("deserialization failure"); + bincode::deserialize(self.inner()).expect("deserialization failure"); // Generate the secret key using Diffie-Hellman exchange let inner_secret_key = InnerSecretKey::from_dh_exchange(&cipher.pk, sk.inner()); @@ -131,6 +146,10 @@ fn test_encryption() { // Decryption let decryption = cipher.decrypt(&receiver_sk).unwrap(); - assert_eq!(message, decryption); + + let cipher_words = cipher.as_words(); + let cipher_from_words = Ciphertext::from_words(&cipher_words); + let decrypted_from_words = cipher_from_words.decrypt(&receiver_sk).unwrap(); + assert_eq!(message, decrypted_from_words); } diff --git a/arm/src/logic_instance.rs b/arm/src/logic_instance.rs index 0fc47d8b..ca38ae02 100644 --- a/arm/src/logic_instance.rs +++ b/arm/src/logic_instance.rs @@ -9,14 +9,50 @@ pub struct LogicInstance { pub tag: Vec, pub is_consumed: bool, pub root: Vec, - pub cipher: Vec, - pub app_data: Vec, + pub app_data: AppData, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[cfg_attr(feature = "nif", derive(NifStruct))] +#[cfg_attr(feature = "nif", module = "Anoma.Arm.AppData")] +pub struct AppData { + pub resource_payload: Vec, + pub discovery_payload: Vec, + pub external_payload: Vec, + pub application_payload: Vec, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Anoma.Arm.ExpirableBlob")] pub struct ExpirableBlob { - pub blob: Vec, - pub deletion_criterion: u8, + pub blob: Vec, + pub deletion_criterion: u32, +} + +impl AppData { + pub fn new() -> Self { + AppData { + resource_payload: Vec::new(), + discovery_payload: Vec::new(), + external_payload: Vec::new(), + application_payload: Vec::new(), + } + } + + pub fn add_resource_payload(&mut self, blob: ExpirableBlob) { + self.resource_payload.push(blob); + } + + pub fn add_discovery_payload(&mut self, blob: ExpirableBlob) { + self.discovery_payload.push(blob); + } + + pub fn add_external_payload(&mut self, blob: ExpirableBlob) { + self.external_payload.push(blob); + } + + pub fn add_application_payload(&mut self, blob: ExpirableBlob) { + self.application_payload.push(blob); + } } diff --git a/arm/src/logic_proof.rs b/arm/src/logic_proof.rs index df71bdcc..9e738626 100644 --- a/arm/src/logic_proof.rs +++ b/arm/src/logic_proof.rs @@ -1,15 +1,20 @@ use crate::{ action_tree::ACTION_TREE_DEPTH, constants::{PADDING_LOGIC_PK, PADDING_LOGIC_VK}, + logic_instance::AppData, logic_instance::LogicInstance, merkle_path::MerklePath, nullifier_key::{NullifierKey, NullifierKeyCommitment}, proving_system::{journal_to_instance, prove, verify as verify_proof}, resource::Resource, resource_logic::TrivialLogicWitness, + utils::words_to_bytes, }; use rand::Rng; -use risc0_zkvm::sha::{Digest, DIGEST_WORDS}; +use risc0_zkvm::{ + serde::to_vec, + sha::{Digest, DIGEST_WORDS}, +}; #[cfg(feature = "nif")] use rustler::NifStruct; use serde::{Deserialize, Serialize}; @@ -27,9 +32,9 @@ pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> { fn witness(&self) -> &Self::Witness; - fn prove(&self) -> LogicProof { + fn prove(&self) -> LogicVerifier { let (proof, instance) = prove(Self::proving_key(), self.witness()); - LogicProof { + LogicVerifier { // TODO: handle the unwrap properly proof, instance, @@ -40,14 +45,24 @@ pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> { #[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(feature = "nif", derive(NifStruct))] -#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicProof")] -pub struct LogicProof { +#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicVerifier")] +pub struct LogicVerifier { pub proof: Vec, pub instance: Vec, pub verifying_key: Vec, } -impl LogicProof { +#[derive(Clone, Debug, Deserialize, Serialize)] +#[cfg_attr(feature = "nif", derive(NifStruct))] +#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicVerifierInputs")] +pub struct LogicVerifierInputs { + pub tag: Vec, + pub verifying_key: Vec, + pub app_data: AppData, + pub proof: Vec, +} + +impl LogicVerifier { pub fn verify(&self) -> bool { let vk = if self.verifying_key.len() == DIGEST_WORDS { let words: [u32; DIGEST_WORDS] = self.verifying_key.clone().try_into().unwrap(); @@ -64,6 +79,39 @@ impl LogicProof { } } +impl LogicVerifierInputs { + pub fn to_logic_verifier(self, is_consumed: bool, root: Vec) -> LogicVerifier { + let instance_words = to_vec(&self.to_instance(is_consumed, root)) + .expect("Failed to serialize LogicInstance"); + LogicVerifier { + proof: self.proof, + instance: words_to_bytes(&instance_words).to_vec(), + verifying_key: self.verifying_key, + } + } + + fn to_instance(&self, is_consumed: bool, root: Vec) -> LogicInstance { + LogicInstance { + tag: self.tag.clone(), + is_consumed, + root, + app_data: self.app_data.clone(), + } + } +} + +impl From for LogicVerifierInputs { + fn from(logic_proof: LogicVerifier) -> Self { + let instance = logic_proof.get_instance(); + LogicVerifierInputs { + tag: instance.tag, + verifying_key: logic_proof.verifying_key, + app_data: instance.app_data, + proof: logic_proof.proof, + } + } +} + #[derive(Clone, Deserialize, Serialize)] pub struct PaddingResourceLogic { witness: TrivialLogicWitness, diff --git a/arm/src/resource_logic.rs b/arm/src/resource_logic.rs index 12f555e9..258371ea 100644 --- a/arm/src/resource_logic.rs +++ b/arm/src/resource_logic.rs @@ -1,5 +1,5 @@ use crate::{ - action_tree::ACTION_TREE_DEPTH, logic_instance::ExpirableBlob, logic_instance::LogicInstance, + action_tree::ACTION_TREE_DEPTH, logic_instance::AppData, logic_instance::LogicInstance, merkle_path::MerklePath, nullifier_key::NullifierKey, resource::Resource, }; use serde::{Deserialize, Serialize}; @@ -43,17 +43,7 @@ impl LogicCircuit for TrivialLogicWitness { tag: tag.as_words().to_vec(), is_consumed: self.is_consumed, // It can be either consumed or created to reduce padding resources root, - cipher: vec![63, 127, 191, 255], // some dummy cipher for testing - app_data: vec![ - ExpirableBlob { - blob: vec![31, 63, 95, 127], - deletion_criterion: 0, - }, - ExpirableBlob { - blob: vec![159, 191, 223, 255], - deletion_criterion: 1, - }, - ], // some dummy app data for testing + app_data: AppData::default(), // No app data for trivial logic } } } diff --git a/arm/src/transaction.rs b/arm/src/transaction.rs index 5216b105..7b0a8e82 100644 --- a/arm/src/transaction.rs +++ b/arm/src/transaction.rs @@ -49,7 +49,7 @@ impl Transaction { } } - pub fn verify(&self) -> bool { + pub fn verify(self) -> bool { match &self.delta_proof { Delta::Proof(ref proof) => { let msg = self.get_delta_msg(); @@ -57,7 +57,7 @@ impl Transaction { if DeltaProof::verify(&msg, proof, instance).is_err() { return false; } - for action in &self.actions { + for action in self.actions { if !action.verify() { return false; } @@ -105,7 +105,7 @@ pub fn generate_test_transaction(n_actions: usize) -> Transaction { let (actions, delta_witness) = create_multiple_actions(n_actions); let mut tx = Transaction::create(actions, Delta::Witness(delta_witness)); tx.generate_delta_proof(); - assert!(tx.verify()); + assert!(tx.clone().verify()); tx } diff --git a/arm/src/utils.rs b/arm/src/utils.rs index 801ea721..09abb5df 100644 --- a/arm/src/utils.rs +++ b/arm/src/utils.rs @@ -2,7 +2,7 @@ use risc0_zkvm::sha::{Impl, Sha256, DIGEST_WORDS}; pub fn bytes_to_words(bytes: &[u8]) -> Vec { let mut words = Vec::new(); - for chunk in bytes.chunks(4) { + for chunk in bytes.chunks_exact(4) { let mut word = 0u32; for &byte in chunk { word = (word << 8) | (byte as u32); diff --git a/examples/kudo_application/app/elfs/kudo-main-guest.bin b/examples/kudo_application/app/elfs/kudo-main-guest.bin index c038b011..b48af3ce 100644 Binary files a/examples/kudo_application/app/elfs/kudo-main-guest.bin and b/examples/kudo_application/app/elfs/kudo-main-guest.bin differ diff --git a/examples/kudo_application/app/elfs/simple-kudo-denomination-guest.bin b/examples/kudo_application/app/elfs/simple-kudo-denomination-guest.bin index f7e2ad43..7a92df4b 100644 Binary files a/examples/kudo_application/app/elfs/simple-kudo-denomination-guest.bin and b/examples/kudo_application/app/elfs/simple-kudo-denomination-guest.bin differ diff --git a/examples/kudo_application/app/elfs/simple-kudo-receive-guest.bin b/examples/kudo_application/app/elfs/simple-kudo-receive-guest.bin index 2152e311..199733b8 100644 Binary files a/examples/kudo_application/app/elfs/simple-kudo-receive-guest.bin and b/examples/kudo_application/app/elfs/simple-kudo-receive-guest.bin differ diff --git a/examples/kudo_application/app/src/kudo_main.rs b/examples/kudo_application/app/src/kudo_main.rs index dedfacf2..71aa4fb1 100644 --- a/examples/kudo_application/app/src/kudo_main.rs +++ b/examples/kudo_application/app/src/kudo_main.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; pub const KUDO_LOGIC_ELF: &[u8] = include_bytes!("../elfs/kudo-main-guest.bin"); lazy_static! { pub static ref KUDO_LOGIC_ID: Digest = - Digest::from_hex("079b2a05c035c5eea13acf359515b690f31eb05a22ffde3be5cb87c4f24d284a") + Digest::from_hex("639d1ed04c420c224fe1f4d751b207fd6586ef36a673c220f62c23e47f95981e") .unwrap(); } diff --git a/examples/kudo_application/app/src/simple_denomination.rs b/examples/kudo_application/app/src/simple_denomination.rs index e433156c..0aa5faa2 100644 --- a/examples/kudo_application/app/src/simple_denomination.rs +++ b/examples/kudo_application/app/src/simple_denomination.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; pub const DENOMINATION_ELF: &[u8] = include_bytes!("../elfs/simple-kudo-denomination-guest.bin"); lazy_static! { pub static ref DENOMINATION_ID: Digest = - Digest::from_hex("e909276f48bc961f86e7c7739cce1ab46937d18c1438c4741a05f61f3547b62c") + Digest::from_hex("2074ae290e5ca64511ff2b329408e48cc4202b8e3538af9eb92155dd3779b8eb") .unwrap(); } diff --git a/examples/kudo_application/app/src/simple_receive.rs b/examples/kudo_application/app/src/simple_receive.rs index 0f15a8b9..82b7b253 100644 --- a/examples/kudo_application/app/src/simple_receive.rs +++ b/examples/kudo_application/app/src/simple_receive.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; pub const RECEIVE_ELF: &[u8] = include_bytes!("../elfs/simple-kudo-receive-guest.bin"); lazy_static! { pub static ref RECEIVE_ID: Digest = - Digest::from_hex("3af6c164f3668562367617ffcb5324241cdfd2fc4b42f3468aa2bb67ae31b854") + Digest::from_hex("9801521c4cfcd46de698a6137fab70a14f88a4e95fd32e3e34fb7b80952d205a") .unwrap(); } diff --git a/examples/kudo_application/logic_witness/src/kudo_main_witness.rs b/examples/kudo_application/logic_witness/src/kudo_main_witness.rs index b19d6793..08764d3b 100644 --- a/examples/kudo_application/logic_witness/src/kudo_main_witness.rs +++ b/examples/kudo_application/logic_witness/src/kudo_main_witness.rs @@ -4,7 +4,7 @@ use arm::{ action_tree::ACTION_TREE_DEPTH, authorization::{AuthorizationSignature, AuthorizationVerifyingKey}, encryption::{Ciphertext, SecretKey}, - logic_instance::LogicInstance, + logic_instance::{AppData, ExpirableBlob, LogicInstance}, merkle_path::MerklePath, nullifier_key::NullifierKey, resource::Resource, @@ -102,14 +102,23 @@ impl LogicCircuit for KudoMainWitness { } // Generate the ciphertext - let cipher = self.generate_ciphertext().inner(); + let cipher = self.generate_ciphertext().as_words(); + let cipher_expirable_blob = ExpirableBlob { + blob: cipher, + deletion_criterion: 1, + }; + let app_data = AppData { + resource_payload: vec![cipher_expirable_blob], + discovery_payload: Vec::new(), + external_payload: Vec::new(), + application_payload: Vec::new(), + }; LogicInstance { tag: tag.as_words().to_vec(), is_consumed: self.kudo_is_consumed, root, - cipher, - app_data: Vec::new(), + app_data, } } } diff --git a/examples/kudo_application/logic_witness/src/simple_denomination_witness.rs b/examples/kudo_application/logic_witness/src/simple_denomination_witness.rs index fe6ef46a..2f40014b 100644 --- a/examples/kudo_application/logic_witness/src/simple_denomination_witness.rs +++ b/examples/kudo_application/logic_witness/src/simple_denomination_witness.rs @@ -3,8 +3,7 @@ pub use arm::resource_logic::LogicCircuit; use arm::{ action_tree::ACTION_TREE_DEPTH, authorization::{AuthorizationSignature, AuthorizationVerifyingKey}, - encryption::Ciphertext, - logic_instance::LogicInstance, + logic_instance::{AppData, LogicInstance}, merkle_path::MerklePath, nullifier_key::NullifierKey, resource::Resource, @@ -93,8 +92,7 @@ impl LogicCircuit for SimpleDenominationLogicWitness { tag: denomination_tag.as_words().to_vec(), is_consumed: self.denomination_is_consumed, root, - cipher: Ciphertext::default().inner(), // no cipher needed - app_data: Vec::new(), // no app data needed + app_data: AppData::default(), // no app data needed } } } diff --git a/examples/kudo_application/logic_witness/src/simple_receive_witness.rs b/examples/kudo_application/logic_witness/src/simple_receive_witness.rs index 9ae572cd..1637ef69 100644 --- a/examples/kudo_application/logic_witness/src/simple_receive_witness.rs +++ b/examples/kudo_application/logic_witness/src/simple_receive_witness.rs @@ -1,7 +1,10 @@ pub use arm::resource_logic::LogicCircuit; use arm::{ - action_tree::ACTION_TREE_DEPTH, encryption::Ciphertext, logic_instance::LogicInstance, - merkle_path::MerklePath, nullifier_key::NullifierKey, resource::Resource, + action_tree::ACTION_TREE_DEPTH, + logic_instance::{AppData, LogicInstance}, + merkle_path::MerklePath, + nullifier_key::NullifierKey, + resource::Resource, }; use serde::{Deserialize, Serialize}; @@ -44,8 +47,7 @@ impl LogicCircuit for SimpleReceiveLogicWitness { tag: tag.as_words().to_vec(), is_consumed: self.is_consumed, // It can be either consumed or created to reduce padding resources root, - cipher: Ciphertext::default().inner(), // no cipher needed - app_data: Vec::new(), // no app data needed + app_data: AppData::default(), // no app data needed } } } diff --git a/examples/simple_counter_application/app/elf/counter-guest.bin b/examples/simple_counter_application/app/elf/counter-guest.bin index 89495d22..f4de3553 100644 Binary files a/examples/simple_counter_application/app/elf/counter-guest.bin and b/examples/simple_counter_application/app/elf/counter-guest.bin differ diff --git a/examples/simple_counter_application/app/src/lib.rs b/examples/simple_counter_application/app/src/lib.rs index ee360525..c75c8cf3 100644 --- a/examples/simple_counter_application/app/src/lib.rs +++ b/examples/simple_counter_application/app/src/lib.rs @@ -11,7 +11,7 @@ use arm::{ }; use arm::{ compliance_unit::ComplianceUnit, - logic_proof::{LogicProof, LogicProver}, + logic_proof::{LogicProver, LogicVerifier}, }; use counter_witness::CounterWitness; use hex::FromHex; @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; pub const SIMPLE_COUNTER_ELF: &[u8] = include_bytes!("../elf/counter-guest.bin"); lazy_static! { pub static ref SIMPLE_COUNTER_ID: Digest = - Digest::from_hex("97a7f988c9c198ccde3a463f5c7cf271e87a81e975c0306322e8c3f1234686ba") + Digest::from_hex("7c6769ff60895aca5e1f45f5865137bac92afb76e63f75e92b4546f4a3a21499") .unwrap(); } @@ -95,7 +95,7 @@ pub fn generate_logic_proofs( consumed_counter: Resource, nf_key: NullifierKey, created_counter: Resource, -) -> Vec { +) -> Vec { let consumed_counter_nf = consumed_counter.nullifier(&nf_key).unwrap(); let created_counter_cm = created_counter.commitment(); diff --git a/examples/simple_counter_application/counter_witness/src/lib.rs b/examples/simple_counter_application/counter_witness/src/lib.rs index ce440f97..6824b6e8 100644 --- a/examples/simple_counter_application/counter_witness/src/lib.rs +++ b/examples/simple_counter_application/counter_witness/src/lib.rs @@ -1,7 +1,10 @@ pub use arm::resource_logic::LogicCircuit; use arm::{ - action_tree::ACTION_TREE_DEPTH, logic_instance::LogicInstance, merkle_path::MerklePath, - nullifier_key::NullifierKey, resource::Resource, + action_tree::ACTION_TREE_DEPTH, + logic_instance::{AppData, LogicInstance}, + merkle_path::MerklePath, + nullifier_key::NullifierKey, + resource::Resource, }; use serde::{Deserialize, Serialize}; #[derive(Clone, Default, Serialize, Deserialize)] @@ -47,8 +50,7 @@ impl LogicCircuit for CounterWitness { tag: tag.as_words().to_vec(), is_consumed: self.is_consumed, root: old_counter_root, - cipher: vec![], - app_data: vec![], + app_data: AppData::default(), } } }