From 6d9d6b3d280315e191b0f1be60902e050f81c809 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 29 Oct 2025 00:40:56 -0300 Subject: [PATCH 1/5] add chained_call field to program output --- nssa/core/src/program.rs | 10 ++++++++++ .../guest/src/bin/privacy_preserving_circuit.rs | 1 + 2 files changed, 11 insertions(+) diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index 82023f3..a96d3cf 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -12,11 +12,20 @@ pub struct ProgramInput { pub instruction: T, } +#[derive(Serialize, Deserialize, Clone)] +#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))] +pub struct ChainedCall { + pub program_id: ProgramId, + pub instruction_data: InstructionData, + pub account_indices: Vec, +} + #[derive(Serialize, Deserialize, Clone)] #[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))] pub struct ProgramOutput { pub pre_states: Vec, pub post_states: Vec, + pub chained_call: Option } pub fn read_nssa_inputs() -> ProgramInput { @@ -33,6 +42,7 @@ pub fn write_nssa_outputs(pre_states: Vec, post_states: Vec let output = ProgramOutput { pre_states, post_states, + chained_call: None }; env::commit(&output); } diff --git a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs index a1aa8c9..1baa5a0 100644 --- a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -27,6 +27,7 @@ fn main() { let ProgramOutput { pre_states, post_states, + chained_call: _, } = program_output; // Check that there are no repeated account ids From 3a277193928b2343d291a8ff8a04783b209d5ca9 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 29 Oct 2025 01:51:09 -0300 Subject: [PATCH 2/5] add tail-chain logic for public transactions --- integration_tests/src/data_changer.bin | Bin 366692 -> 371388 bytes .../src/bin/privacy_preserving_circuit.rs | 7 +- nssa/src/program.rs | 12 ++-- nssa/src/public_transaction/transaction.rs | 67 +++++++++++++++--- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/integration_tests/src/data_changer.bin b/integration_tests/src/data_changer.bin index d201f91960c9f4739d4a4ee0c94fb4a356f50e24..c4fbec0f1c44d11a802a9f10e241da57d768ea88 100644 GIT binary patch delta 95675 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 Dh4?oR delta 92914 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 bSUtX~I!ejRNpDzx4emAaxmG#pb0_{k(z`m7 diff --git a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs index 1baa5a0..345198a 100644 --- a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -27,9 +27,14 @@ fn main() { let ProgramOutput { pre_states, post_states, - chained_call: _, + chained_call, } = program_output; + // TODO: implement tail calls for privacy preserving transactions + if chained_call.is_some() { + panic!("Privacy preserving transactions do not support yet tail calls.") + } + // Check that there are no repeated account ids if !validate_uniqueness_of_account_ids(&pre_states) { panic!("Repeated account ids found") diff --git a/nssa/src/program.rs b/nssa/src/program.rs index 7771aaf..877b01b 100644 --- a/nssa/src/program.rs +++ b/nssa/src/program.rs @@ -48,7 +48,7 @@ impl Program { &self, pre_states: &[AccountWithMetadata], instruction_data: &InstructionData, - ) -> Result, NssaError> { + ) -> Result { // Write inputs to the program let mut env_builder = ExecutorEnv::builder(); env_builder.session_limit(Some(MAX_NUM_CYCLES_PUBLIC_EXECUTION)); @@ -62,12 +62,12 @@ impl Program { .map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?; // Get outputs - let ProgramOutput { post_states, .. } = session_info + let program_output = session_info .journal .decode() .map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?; - Ok(post_states) + Ok(program_output) } /// Writes inputs to `env_builder` in the order expected by the programs @@ -221,12 +221,12 @@ mod tests { balance: balance_to_move, ..Account::default() }; - let [sender_post, recipient_post] = program + let program_output = program .execute(&[sender, recipient], &instruction_data) - .unwrap() - .try_into() .unwrap(); + let [sender_post, recipient_post] = program_output.post_states.try_into().unwrap(); + assert_eq!(sender_post, expected_sender_post); assert_eq!(recipient_post, expected_recipient_post); } diff --git a/nssa/src/public_transaction/transaction.rs b/nssa/src/public_transaction/transaction.rs index b0b8f73..7079074 100644 --- a/nssa/src/public_transaction/transaction.rs +++ b/nssa/src/public_transaction/transaction.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use nssa_core::{ account::{Account, AccountWithMetadata}, address::Address, - program::validate_execution, + program::{ChainedCall, validate_execution}, }; use sha2::{Digest, digest::FixedOutput}; @@ -18,6 +18,7 @@ pub struct PublicTransaction { message: Message, witness_set: WitnessSet, } +const MAX_NUMBER_CHAINED_CALLS: usize = 10; impl PublicTransaction { pub fn new(message: Message, witness_set: WitnessSet) -> Self { @@ -100,21 +101,65 @@ impl PublicTransaction { }) .collect(); - // Check the `program_id` corresponds to a deployed program - let Some(program) = state.programs().get(&message.program_id) else { - return Err(NssaError::InvalidInput("Unknown program".into())); + let mut state_diff: HashMap = message + .addresses + .iter() + .cloned() + .zip(pre_states.iter().map(|pre| pre.account.clone())) + .collect(); + + let mut chained_call = ChainedCall { + program_id: message.program_id, + instruction_data: message.instruction_data.clone(), + account_indices: (0..pre_states.len()).collect(), }; - // // Execute program - let post_states = program.execute(&pre_states, &message.instruction_data)?; + for _ in 0..MAX_NUMBER_CHAINED_CALLS { + // Check the `program_id` corresponds to a deployed program + let Some(program) = state.programs().get(&chained_call.program_id) else { + return Err(NssaError::InvalidInput("Unknown program".into())); + }; - // Verify execution corresponds to a well-behaved program. - // See the # Programs section for the definition of the `validate_execution` method. - if !validate_execution(&pre_states, &post_states, message.program_id) { - return Err(NssaError::InvalidProgramBehavior); + let pre_states_chained_call = chained_call + .account_indices + .iter() + .map(|&i| { + pre_states + .get(i) + .ok_or_else(|| NssaError::InvalidInput("Invalid account indices".into())) + .cloned() + }) + .collect::, NssaError>>()?; + + let program_output = + program.execute(&pre_states_chained_call, &chained_call.instruction_data)?; + + // Verify execution corresponds to a well-behaved program. + // See the # Programs section for the definition of the `validate_execution` method. + if validate_execution( + &program_output.pre_states, + &program_output.post_states, + message.program_id, + ) { + for (pre, post) in program_output + .pre_states + .iter() + .zip(program_output.post_states) + { + state_diff.insert(pre.account_id, post); + } + } else { + return Err(NssaError::InvalidProgramBehavior); + } + + if let Some(next_chained_call) = program_output.chained_call { + chained_call = next_chained_call; + } else { + break; + }; } - Ok(message.addresses.iter().cloned().zip(post_states).collect()) + Ok(state_diff) } } From 48fc64395204df128f8d2d47270e16b9745c0d11 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 29 Oct 2025 15:34:11 -0300 Subject: [PATCH 3/5] add chained call test --- nssa/core/src/program.rs | 17 +++++++-- .../src/bin/privacy_preserving_circuit.rs | 4 +-- nssa/src/program.rs | 15 ++++++-- nssa/src/public_transaction/transaction.rs | 4 +-- nssa/src/state.rs | 36 +++++++++++++++++++ nssa/test_program_methods/guest/Cargo.lock | 2 ++ nssa/test_program_methods/guest/Cargo.toml | 2 ++ .../guest/src/bin/chain_caller.rs | 32 +++++++++++++++++ 8 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 nssa/test_program_methods/guest/src/bin/chain_caller.rs diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index a96d3cf..6582984 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -25,7 +25,7 @@ pub struct ChainedCall { pub struct ProgramOutput { pub pre_states: Vec, pub post_states: Vec, - pub chained_call: Option + pub chained_call: Option, } pub fn read_nssa_inputs() -> ProgramInput { @@ -42,7 +42,20 @@ pub fn write_nssa_outputs(pre_states: Vec, post_states: Vec let output = ProgramOutput { pre_states, post_states, - chained_call: None + chained_call: None, + }; + env::commit(&output); +} + +pub fn write_nssa_outputs_with_chained_call( + pre_states: Vec, + post_states: Vec, + chained_call: Option, +) { + let output = ProgramOutput { + pre_states, + post_states, + chained_call, }; env::commit(&output); } diff --git a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs index 345198a..d8ed15d 100644 --- a/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -30,9 +30,9 @@ fn main() { chained_call, } = program_output; - // TODO: implement tail calls for privacy preserving transactions + // TODO: implement chained calls for privacy preserving transactions if chained_call.is_some() { - panic!("Privacy preserving transactions do not support yet tail calls.") + panic!("Privacy preserving transactions do not support yet chained calls.") } // Check that there are no repeated account ids diff --git a/nssa/src/program.rs b/nssa/src/program.rs index 877b01b..11eb413 100644 --- a/nssa/src/program.rs +++ b/nssa/src/program.rs @@ -1,6 +1,6 @@ use crate::program_methods::{AUTHENTICATED_TRANSFER_ELF, PINATA_ELF, TOKEN_ELF}; use nssa_core::{ - account::{Account, AccountWithMetadata}, + account::AccountWithMetadata, program::{InstructionData, ProgramId, ProgramOutput}, }; @@ -107,11 +107,11 @@ impl Program { #[cfg(test)] mod tests { - use nssa_core::account::{Account, AccountId, AccountWithMetadata}; - use program_methods::{ + use crate::program_methods::{ AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID, PINATA_ELF, PINATA_ID, TOKEN_ELF, TOKEN_ID, }; + use nssa_core::account::{Account, AccountId, AccountWithMetadata}; use crate::program::Program; @@ -195,6 +195,15 @@ mod tests { elf: BURNER_ELF.to_vec(), } } + + pub fn chain_caller() -> Self { + use test_program_methods::{CHAIN_CALLER_ELF, CHAIN_CALLER_ID}; + + Program { + id: CHAIN_CALLER_ID, + elf: CHAIN_CALLER_ELF.to_vec(), + } + } } #[test] diff --git a/nssa/src/public_transaction/transaction.rs b/nssa/src/public_transaction/transaction.rs index 7079074..70d22a3 100644 --- a/nssa/src/public_transaction/transaction.rs +++ b/nssa/src/public_transaction/transaction.rs @@ -114,7 +114,7 @@ impl PublicTransaction { account_indices: (0..pre_states.len()).collect(), }; - for _ in 0..MAX_NUMBER_CHAINED_CALLS { + for _i in 0..MAX_NUMBER_CHAINED_CALLS { // Check the `program_id` corresponds to a deployed program let Some(program) = state.programs().get(&chained_call.program_id) else { return Err(NssaError::InvalidInput("Unknown program".into())); @@ -139,7 +139,7 @@ impl PublicTransaction { if validate_execution( &program_output.pre_states, &program_output.post_states, - message.program_id, + chained_call.program_id, ) { for (pre, post) in program_output .pre_states diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 83183f5..5a0b87b 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -263,6 +263,7 @@ pub mod tests { Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey, account::{Account, AccountId, AccountWithMetadata, Nonce}, encryption::{EphemeralPublicKey, IncomingViewingPublicKey, Scalar}, + program::ProgramId, }; fn transfer_transaction( @@ -475,6 +476,7 @@ pub mod tests { self.insert_program(Program::data_changer()); self.insert_program(Program::minter()); self.insert_program(Program::burner()); + self.insert_program(Program::chain_caller()); self } @@ -2045,4 +2047,38 @@ pub mod tests { assert!(matches!(result, Err(NssaError::CircuitProvingError(_)))); } + + #[test] + fn test_chained_call() { + let program = Program::chain_caller(); + let key = PrivateKey::try_new([1; 32]).unwrap(); + let address = Address::from(&PublicKey::new_from_private_key(&key)); + let initial_balance = 100; + let initial_data = [(address, initial_balance)]; + let mut state = + V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs(); + let from = address; + let from_key = key; + let to = Address::new([2; 32]); + let amount: u128 = 37; + let instruction: (u128, ProgramId) = + (amount, Program::authenticated_transfer_program().id()); + + let message = public_transaction::Message::try_new( + program.id(), + vec![to, from], + vec![0], + instruction, + ) + .unwrap(); + let witness_set = public_transaction::WitnessSet::for_message(&message, &[&from_key]); + let tx = PublicTransaction::new(message, witness_set); + + state.transition_from_public_transaction(&tx).unwrap(); + + let from_post = state.get_account_by_address(&from); + let to_post = state.get_account_by_address(&to); + assert_eq!(from_post.balance, initial_balance - amount); + assert_eq!(to_post.balance, amount); + } } diff --git a/nssa/test_program_methods/guest/Cargo.lock b/nssa/test_program_methods/guest/Cargo.lock index 8cb2bec..d7e5b67 100644 --- a/nssa/test_program_methods/guest/Cargo.lock +++ b/nssa/test_program_methods/guest/Cargo.lock @@ -1824,6 +1824,8 @@ name = "programs" version = "0.1.0" dependencies = [ "nssa-core", + "risc0-zkvm", + "serde", ] [[package]] diff --git a/nssa/test_program_methods/guest/Cargo.toml b/nssa/test_program_methods/guest/Cargo.toml index 2289292..9e5f543 100644 --- a/nssa/test_program_methods/guest/Cargo.toml +++ b/nssa/test_program_methods/guest/Cargo.toml @@ -6,4 +6,6 @@ edition = "2024" [workspace] [dependencies] +risc0-zkvm = { version = "3.0.3", features = ['std'] } nssa-core = { path = "../../core" } +serde = { version = "1.0.219", default-features = false } diff --git a/nssa/test_program_methods/guest/src/bin/chain_caller.rs b/nssa/test_program_methods/guest/src/bin/chain_caller.rs new file mode 100644 index 0000000..321d032 --- /dev/null +++ b/nssa/test_program_methods/guest/src/bin/chain_caller.rs @@ -0,0 +1,32 @@ +use nssa_core::program::{ + ChainedCall, ProgramId, ProgramInput, read_nssa_inputs, write_nssa_outputs_with_chained_call, +}; +use risc0_zkvm::serde::to_vec; + +type Instruction = (u128, ProgramId); + +fn main() { + let ProgramInput { + pre_states, + instruction: (balance, program_id), + } = read_nssa_inputs::(); + + let [sender_pre, receiver_pre] = match pre_states.try_into() { + Ok(array) => array, + Err(_) => return, + }; + + let instruction_data = to_vec(&balance).unwrap(); + + let chained_call = Some(ChainedCall { + program_id, + instruction_data, + account_indices: vec![1, 0], + }); + + write_nssa_outputs_with_chained_call( + vec![sender_pre.clone(), receiver_pre.clone()], + vec![sender_pre.account, receiver_pre.account], + chained_call, + ); +} From 0fb72e452f5b021e365d7a2ba8ca144003b80e4a Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Thu, 30 Oct 2025 10:52:31 -0300 Subject: [PATCH 4/5] fix claiming mechanism for chained calls --- nssa/core/src/program.rs | 7 ++- nssa/src/public_transaction/transaction.rs | 29 ++++++---- nssa/src/state.rs | 54 ++++++++++++++++--- .../guest/src/bin/chain_caller.rs | 4 +- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index 6582984..3ecee30 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -102,9 +102,14 @@ pub fn validate_execution( { return false; } + + // 6. If a post state has default program owner, the pre state must have been a default account + if post.program_owner == DEFAULT_PROGRAM_ID && pre.account != Account::default() { + return false; + } } - // 6. Total balance is preserved + // 7. Total balance is preserved let total_balance_pre_states: u128 = pre_states.iter().map(|pre| pre.account.balance).sum(); let total_balance_post_states: u128 = post_states.iter().map(|post| post.balance).sum(); if total_balance_pre_states != total_balance_post_states { diff --git a/nssa/src/public_transaction/transaction.rs b/nssa/src/public_transaction/transaction.rs index 70d22a3..900a476 100644 --- a/nssa/src/public_transaction/transaction.rs +++ b/nssa/src/public_transaction/transaction.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use nssa_core::{ account::{Account, AccountWithMetadata}, address::Address, - program::{ChainedCall, validate_execution}, + program::{ChainedCall, DEFAULT_PROGRAM_ID, validate_execution}, }; use sha2::{Digest, digest::FixedOutput}; @@ -131,27 +131,34 @@ impl PublicTransaction { }) .collect::, NssaError>>()?; - let program_output = + let mut program_output = program.execute(&pre_states_chained_call, &chained_call.instruction_data)?; // Verify execution corresponds to a well-behaved program. // See the # Programs section for the definition of the `validate_execution` method. - if validate_execution( + if !validate_execution( &program_output.pre_states, &program_output.post_states, chained_call.program_id, ) { - for (pre, post) in program_output - .pre_states - .iter() - .zip(program_output.post_states) - { - state_diff.insert(pre.account_id, post); - } - } else { return Err(NssaError::InvalidProgramBehavior); } + for post in program_output.post_states.iter_mut() { + // The invoked program claims the accounts with default program id. + if post.program_owner == DEFAULT_PROGRAM_ID { + post.program_owner = chained_call.program_id; + } + } + + for (pre, post) in program_output + .pre_states + .iter() + .zip(program_output.post_states) + { + state_diff.insert(pre.account_id, post); + } + if let Some(next_chained_call) = program_output.chained_call { chained_call = next_chained_call; } else { diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 5a0b87b..2119929 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -8,7 +8,7 @@ use nssa_core::{ Commitment, CommitmentSetDigest, DUMMY_COMMITMENT, MembershipProof, Nullifier, account::Account, address::Address, - program::{DEFAULT_PROGRAM_ID, ProgramId}, + program::ProgramId, }; use std::collections::{HashMap, HashSet}; @@ -114,10 +114,6 @@ impl V02State { let current_account = self.get_account_by_address_mut(address); *current_account = post; - // The invoked program claims the accounts with default program id. - if current_account.program_owner == DEFAULT_PROGRAM_ID { - current_account.program_owner = tx.message().program_id; - } } for address in tx.signer_addresses() { @@ -437,7 +433,7 @@ pub mod tests { } #[test] - fn transition_from_chained_authenticated_transfer_program_invocations() { + fn transition_from_sequence_of_authenticated_transfer_program_invocations() { let key1 = PrivateKey::try_new([8; 32]).unwrap(); let address1 = Address::from(&PublicKey::new_from_private_key(&key1)); let key2 = PrivateKey::try_new([2; 32]).unwrap(); @@ -2048,6 +2044,42 @@ pub mod tests { assert!(matches!(result, Err(NssaError::CircuitProvingError(_)))); } + #[test] + fn test_claiming_mechanism() { + let program = Program::authenticated_transfer_program(); + let key = PrivateKey::try_new([1; 32]).unwrap(); + let address = Address::from(&PublicKey::new_from_private_key(&key)); + let initial_balance = 100; + let initial_data = [(address, initial_balance)]; + let mut state = + V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs(); + let from = address; + let from_key = key; + let to = Address::new([2; 32]); + let amount: u128 = 37; + + // Check the recipient is an uninitialized account + assert_eq!(state.get_account_by_address(&to), Account::default()); + + let expected_recipient_post = Account { + program_owner: program.id(), + balance: amount, + ..Account::default() + }; + + let message = + public_transaction::Message::try_new(program.id(), vec![from, to], vec![0], amount) + .unwrap(); + let witness_set = public_transaction::WitnessSet::for_message(&message, &[&from_key]); + let tx = PublicTransaction::new(message, witness_set); + + state.transition_from_public_transaction(&tx).unwrap(); + + let recipient_post = state.get_account_by_address(&to); + + assert_eq!(recipient_post, expected_recipient_post); + } + #[test] fn test_chained_call() { let program = Program::chain_caller(); @@ -2064,9 +2096,15 @@ pub mod tests { let instruction: (u128, ProgramId) = (amount, Program::authenticated_transfer_program().id()); + let expected_to_post = Account { + program_owner: Program::authenticated_transfer_program().id(), + balance: amount, + ..Account::default() + }; + let message = public_transaction::Message::try_new( program.id(), - vec![to, from], + vec![to, from], //The chain_caller program permutes the account order in the chain call vec![0], instruction, ) @@ -2079,6 +2117,6 @@ pub mod tests { let from_post = state.get_account_by_address(&from); let to_post = state.get_account_by_address(&to); assert_eq!(from_post.balance, initial_balance - amount); - assert_eq!(to_post.balance, amount); + assert_eq!(to_post, expected_to_post); } } diff --git a/nssa/test_program_methods/guest/src/bin/chain_caller.rs b/nssa/test_program_methods/guest/src/bin/chain_caller.rs index 321d032..dfd77b1 100644 --- a/nssa/test_program_methods/guest/src/bin/chain_caller.rs +++ b/nssa/test_program_methods/guest/src/bin/chain_caller.rs @@ -5,6 +5,8 @@ use risc0_zkvm::serde::to_vec; type Instruction = (u128, ProgramId); +/// A program that calls another program. +/// It permutes the order of the input accounts on the subsequent call fn main() { let ProgramInput { pre_states, @@ -21,7 +23,7 @@ fn main() { let chained_call = Some(ChainedCall { program_id, instruction_data, - account_indices: vec![1, 0], + account_indices: vec![1, 0], // <- Account order permutation here }); write_nssa_outputs_with_chained_call( From 12974f6f6b8662d4107b8e04d3baaa28c7dc32ad Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Thu, 30 Oct 2025 13:47:52 -0300 Subject: [PATCH 5/5] refactor --- nssa/src/public_transaction/transaction.rs | 78 +++++++++++++--------- nssa/src/state.rs | 6 +- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/nssa/src/public_transaction/transaction.rs b/nssa/src/public_transaction/transaction.rs index 900a476..d118d0c 100644 --- a/nssa/src/public_transaction/transaction.rs +++ b/nssa/src/public_transaction/transaction.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use nssa_core::{ account::{Account, AccountWithMetadata}, address::Address, - program::{ChainedCall, DEFAULT_PROGRAM_ID, validate_execution}, + program::{DEFAULT_PROGRAM_ID, validate_execution}, }; use sha2::{Digest, digest::FixedOutput}; @@ -89,7 +89,7 @@ impl PublicTransaction { } // Build pre_states for execution - let pre_states: Vec<_> = message + let mut input_pre_states: Vec<_> = message .addresses .iter() .map(|address| { @@ -101,66 +101,80 @@ impl PublicTransaction { }) .collect(); - let mut state_diff: HashMap = message - .addresses - .iter() - .cloned() - .zip(pre_states.iter().map(|pre| pre.account.clone())) - .collect(); + let mut state_diff: HashMap = HashMap::new(); - let mut chained_call = ChainedCall { - program_id: message.program_id, - instruction_data: message.instruction_data.clone(), - account_indices: (0..pre_states.len()).collect(), - }; + let mut program_id = message.program_id; + let mut instruction_data = message.instruction_data.clone(); for _i in 0..MAX_NUMBER_CHAINED_CALLS { // Check the `program_id` corresponds to a deployed program - let Some(program) = state.programs().get(&chained_call.program_id) else { + let Some(program) = state.programs().get(&program_id) else { return Err(NssaError::InvalidInput("Unknown program".into())); }; - let pre_states_chained_call = chained_call - .account_indices - .iter() - .map(|&i| { - pre_states - .get(i) - .ok_or_else(|| NssaError::InvalidInput("Invalid account indices".into())) - .cloned() - }) - .collect::, NssaError>>()?; + let mut program_output = program.execute(&input_pre_states, &instruction_data)?; - let mut program_output = - program.execute(&pre_states_chained_call, &chained_call.instruction_data)?; + // This check is equivalent to checking that the program output pre_states coinicide + // with the values in the public state or with any modifications to those values + // during the chain of calls. + if input_pre_states != program_output.pre_states { + return Err(NssaError::InvalidProgramBehavior); + } // Verify execution corresponds to a well-behaved program. // See the # Programs section for the definition of the `validate_execution` method. if !validate_execution( &program_output.pre_states, &program_output.post_states, - chained_call.program_id, + program_id, ) { return Err(NssaError::InvalidProgramBehavior); } + // The invoked program claims the accounts with default program id. for post in program_output.post_states.iter_mut() { - // The invoked program claims the accounts with default program id. if post.program_owner == DEFAULT_PROGRAM_ID { - post.program_owner = chained_call.program_id; + post.program_owner = program_id; } } + // Update the state diff for (pre, post) in program_output .pre_states .iter() - .zip(program_output.post_states) + .zip(program_output.post_states.iter()) { - state_diff.insert(pre.account_id, post); + state_diff.insert(pre.account_id, post.clone()); } if let Some(next_chained_call) = program_output.chained_call { - chained_call = next_chained_call; + program_id = next_chained_call.program_id; + instruction_data = next_chained_call.instruction_data; + + // Build post states with metadata for next call + let mut post_states_with_metadata = Vec::new(); + for (pre, post) in program_output + .pre_states + .iter() + .zip(program_output.post_states) + { + let mut post_with_metadata = pre.clone(); + post_with_metadata.account = post.clone(); + post_states_with_metadata.push(post_with_metadata); + } + + input_pre_states = next_chained_call + .account_indices + .iter() + .map(|&i| { + post_states_with_metadata + .get(i) + .ok_or_else(|| { + NssaError::InvalidInput("Invalid account indices".into()) + }) + .cloned() + }) + .collect::, NssaError>>()?; } else { break; }; diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 2119929..4120824 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -6,9 +6,7 @@ use crate::{ }; use nssa_core::{ Commitment, CommitmentSetDigest, DUMMY_COMMITMENT, MembershipProof, Nullifier, - account::Account, - address::Address, - program::ProgramId, + account::Account, address::Address, program::ProgramId, }; use std::collections::{HashMap, HashSet}; @@ -2097,7 +2095,7 @@ pub mod tests { (amount, Program::authenticated_transfer_program().id()); let expected_to_post = Account { - program_owner: Program::authenticated_transfer_program().id(), + program_owner: Program::chain_caller().id(), balance: amount, ..Account::default() };