From 507988832f7027d6e153f3d96fbc736f1c509df9 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Thu, 14 Aug 2025 15:34:21 -0300 Subject: [PATCH] add transition_from_privacy_preserving_transaction method and relevant scaffolding --- nssa/core/src/account/commitment.rs | 2 +- nssa/core/src/account/nullifier.rs | 2 +- .../privacy_preserving_transaction/message.rs | 12 ++--- .../src/privacy_preserving_transaction/mod.rs | 2 + .../transaction.rs | 30 +++++++++++ .../witness_set.rs | 21 +++++++- nssa/src/state.rs | 52 +++++++++++++++++-- 7 files changed, 109 insertions(+), 12 deletions(-) diff --git a/nssa/core/src/account/commitment.rs b/nssa/core/src/account/commitment.rs index 5bb7532..a0bcfee 100644 --- a/nssa/core/src/account/commitment.rs +++ b/nssa/core/src/account/commitment.rs @@ -1,2 +1,2 @@ -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Commitment([u8; 32]); diff --git a/nssa/core/src/account/nullifier.rs b/nssa/core/src/account/nullifier.rs index 3280f19..4479af0 100644 --- a/nssa/core/src/account/nullifier.rs +++ b/nssa/core/src/account/nullifier.rs @@ -1,2 +1,2 @@ -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Nullifier([u8; 32]); diff --git a/nssa/src/privacy_preserving_transaction/message.rs b/nssa/src/privacy_preserving_transaction/message.rs index edea889..1585be1 100644 --- a/nssa/src/privacy_preserving_transaction/message.rs +++ b/nssa/src/privacy_preserving_transaction/message.rs @@ -7,10 +7,10 @@ struct EncryptedAccountData; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Message { - public_addresses: Vec
, - nonces: Vec, - public_post_states: Vec, - encrypted_private_post_states: Vec, - new_commitments: Vec, - new_nullifiers: Vec, + pub(crate) public_addresses: Vec
, + pub(crate) nonces: Vec, + pub(crate) public_post_states: Vec, + pub(crate) encrypted_private_post_states: Vec, + pub(crate) new_commitments: Vec, + pub(crate) new_nullifiers: Vec, } diff --git a/nssa/src/privacy_preserving_transaction/mod.rs b/nssa/src/privacy_preserving_transaction/mod.rs index 898d27c..2d3bba3 100644 --- a/nssa/src/privacy_preserving_transaction/mod.rs +++ b/nssa/src/privacy_preserving_transaction/mod.rs @@ -1,3 +1,5 @@ mod transaction; mod message; mod witness_set; + +pub use transaction::PrivacyPreservingTransaction; diff --git a/nssa/src/privacy_preserving_transaction/transaction.rs b/nssa/src/privacy_preserving_transaction/transaction.rs index 7322c75..0640454 100644 --- a/nssa/src/privacy_preserving_transaction/transaction.rs +++ b/nssa/src/privacy_preserving_transaction/transaction.rs @@ -1,3 +1,10 @@ +use std::collections::HashMap; + +use nssa_core::account::Account; + +use crate::error::NssaError; +use crate::{Address, V01State}; + use super::message::Message; use super::witness_set::WitnessSet; @@ -7,4 +14,27 @@ pub struct PrivacyPreservingTransaction { witness_set: WitnessSet, } +impl PrivacyPreservingTransaction { + pub(crate) fn validate( + &self, + arg: &mut V01State, + ) -> Result, NssaError> { + todo!() + } + pub fn message(&self) -> &Message { + &self.message + } + + pub fn witness_set(&self) -> &WitnessSet { + &self.witness_set + } + + pub(crate) fn signer_addresses(&self) -> Vec
{ + self.witness_set + .signatures_and_public_keys() + .iter() + .map(|(_, public_key)| Address::from_public_key(public_key)) + .collect() + } +} diff --git a/nssa/src/privacy_preserving_transaction/witness_set.rs b/nssa/src/privacy_preserving_transaction/witness_set.rs index 132bb49..6a65cb6 100644 --- a/nssa/src/privacy_preserving_transaction/witness_set.rs +++ b/nssa/src/privacy_preserving_transaction/witness_set.rs @@ -1,2 +1,21 @@ +use crate::{privacy_preserving_transaction::message::Message, PrivateKey, PublicKey, Signature}; + #[derive(Debug, Clone, PartialEq, Eq)] -pub struct WitnessSet; +pub struct WitnessSet { + pub(super) signatures_and_public_keys: Vec<(Signature, PublicKey)>, +} + + +impl WitnessSet { + pub fn for_message(message: &Message, private_keys: &[&PrivateKey]) -> Self { + todo!() + } + + pub fn is_valid_for(&self, message: &Message) -> bool { + todo!() + } + + pub fn signatures_and_public_keys(&self) -> &[(Signature, PublicKey)] { + &self.signatures_and_public_keys + } +} diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 3060185..3e266d8 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -1,14 +1,31 @@ use crate::{ - address::Address, error::NssaError, program::Program, public_transaction::PublicTransaction, + address::Address, error::NssaError, + privacy_preserving_transaction::PrivacyPreservingTransaction, program::Program, + public_transaction::PublicTransaction, }; use nssa_core::{ - account::Account, + account::{Account, Commitment, Nullifier}, program::{DEFAULT_PROGRAM_ID, ProgramId}, }; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; + +struct CommitmentSet(HashSet); + +impl CommitmentSet { + fn extend(&mut self, commitments: &[Commitment]) { + self.0.extend(commitments) + } + + fn set_commitment(&self) -> [u8; 32] { + // TODO: implement + [0; 32] + } +} +type NullifierSet = HashSet; pub struct V01State { public_state: HashMap, + private_state: (CommitmentSet, NullifierSet), builtin_programs: HashMap, } @@ -31,6 +48,7 @@ impl V01State { let mut this = Self { public_state, + private_state: (CommitmentSet(HashSet::new()), NullifierSet::new()), builtin_programs: HashMap::new(), }; @@ -67,6 +85,34 @@ impl V01State { Ok(()) } + pub fn transition_from_privacy_preserving_transaction( + &mut self, + tx: &PrivacyPreservingTransaction, + ) -> Result<(), NssaError> { + // 1. Verify the transaction satisfies acceptance criteria + let public_state_diff = tx.validate(self)?; + let message = tx.message(); + + // 2. Add new commitments + self.private_state.0.extend(message.new_commitments); + + // 3. Add new nullifiers + self.private_state.1.extend(message.new_nullifiers); + + // 4. Update public accounts + for (address, post) in public_state_diff.into_iter() { + let current_account = self.get_account_by_address_mut(address); + *current_account = post; + } + + // // 5. Increment nonces + for address in tx.signer_addresses() { + let current_account = self.get_account_by_address_mut(address); + current_account.nonce += 1; + } + Ok(()) + } + fn get_account_by_address_mut(&mut self, address: Address) -> &mut Account { self.public_state.entry(address).or_default() }