diff --git a/src/bin/tx.rs b/src/bin/tx.rs index 8d0f0a7e0..9676ce7d1 100644 --- a/src/bin/tx.rs +++ b/src/bin/tx.rs @@ -34,8 +34,8 @@ impl ProgramState for MemoryState { fn is_valid_merkle(&self, merkle: &bls12_381::Scalar) -> bool { self.merkle_roots.iter().any(|m| *m == *merkle) } - fn nullifier_exists(&self, nullifier: &[u8; 32]) -> bool { - self.nullifiers.iter().any(|n| n.repr == *nullifier) + fn nullifier_exists(&self, nullifier: &Nullifier) -> bool { + self.nullifiers.iter().any(|n| n.repr == nullifier.repr) } fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey { @@ -47,7 +47,7 @@ impl ProgramState for MemoryState { } impl MemoryState { - async fn apply(&mut self, mut updates: StateUpdates) { + fn apply(&mut self, mut updates: StateUpdates) { self.nullifiers.append(&mut updates.nullifiers); // Update merkle tree and witnesses @@ -184,8 +184,10 @@ fn main() { let tx = tx::Transaction::decode(&tx_data[..]).unwrap(); let update = state_transition(&state, tx).expect("step 2 state transition failed"); - - smol::block_on(state.apply(update)); + // Our state impl is memory online for this demo + // but in the real version, this function will be async + // and using the databases. + state.apply(update); } // Wallet1 has received payment from the cashier. diff --git a/src/crypto/nullifier.rs b/src/crypto/nullifier.rs index 1732cbda5..1170377a3 100644 --- a/src/crypto/nullifier.rs +++ b/src/crypto/nullifier.rs @@ -1,3 +1,7 @@ +use std::io; + +use crate::{error::Result, serial::{Decodable, Encodable}}; + pub struct Nullifier { pub repr: [u8; 32], } @@ -7,3 +11,17 @@ impl Nullifier { Self { repr } } } + +impl Encodable for Nullifier { + fn encode(&self, mut s: S) -> Result { + Ok(self.repr.encode(s)?) + } +} + +impl Decodable for Nullifier { + fn decode(mut d: D) -> Result { + Ok(Self { + repr: Decodable::decode(d)?, + }) + } +} diff --git a/src/crypto/spend_proof.rs b/src/crypto/spend_proof.rs index 776e153bb..d37fe39c6 100644 --- a/src/crypto/spend_proof.rs +++ b/src/crypto/spend_proof.rs @@ -12,10 +12,11 @@ use super::node::merkle_hash; use crate::circuit::spend_contract::SpendContract; use crate::error::Result; use crate::serial::{Decodable, Encodable}; +use super::nullifier::Nullifier; pub struct SpendRevealedValues { pub value_commit: jubjub::SubgroupPoint, - pub nullifier: [u8; 32], + pub nullifier: Nullifier, // This should not be here, we just have it for debugging //coin: [u8; 32], pub merkle_root: bls12_381::Scalar, @@ -48,6 +49,7 @@ impl SpendRevealedValues { .finalize() .as_bytes(), ); + let nullifier = Nullifier::new(nullifier); let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret; let signature_public = @@ -108,7 +110,7 @@ impl SpendRevealedValues { // NF { // Pack the hash as inputs for proof verification. - let hash = multipack::bytes_to_bits_le(&self.nullifier); + let hash = multipack::bytes_to_bits_le(&self.nullifier.repr); let hash = multipack::compute_multipacking(&hash); // There are 2 chunks for a blake hash diff --git a/src/state.rs b/src/state.rs index d351a61a4..7d286b33c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -10,7 +10,7 @@ use crate::{ pub trait ProgramState { fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool; fn is_valid_merkle(&self, merkle: &bls12_381::Scalar) -> bool; - fn nullifier_exists(&self, nullifier: &[u8; 32]) -> bool; + fn nullifier_exists(&self, nullifier: &Nullifier) -> bool; fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey; fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey; @@ -100,7 +100,7 @@ pub fn state_transition( let mut nullifiers = vec![]; for input in tx.inputs { - nullifiers.push(Nullifier::new(input.revealed.nullifier)); + nullifiers.push(input.revealed.nullifier); } // Newly created coins for this tx