mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-07-25 23:23:11 +00:00
Merge branch 'marvin/public_keys' into marvin/public_account_id
This commit is contained in:
+2
-1
@@ -24,8 +24,9 @@ risc0-binfmt = "3.0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
test_program_methods.workspace = true
|
||||
hex-literal = "1.0.0"
|
||||
env_logger.workspace = true
|
||||
hex-literal = "1.0.0"
|
||||
test-case = "3.3.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -15,9 +15,8 @@ pub type Nonce = u128;
|
||||
|
||||
/// Account to be used both in public and private contexts
|
||||
#[derive(
|
||||
Clone, Default, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
|
||||
Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
|
||||
)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug))]
|
||||
pub struct Account {
|
||||
pub program_owner: ProgramId,
|
||||
pub balance: u128,
|
||||
@@ -25,8 +24,7 @@ pub struct Account {
|
||||
pub nonce: Nonce,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug))]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct AccountWithMetadata {
|
||||
pub account: Account,
|
||||
pub is_authorized: bool,
|
||||
@@ -45,6 +43,7 @@ impl AccountWithMetadata {
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
Copy,
|
||||
Clone,
|
||||
@@ -56,7 +55,7 @@ impl AccountWithMetadata {
|
||||
BorshSerialize,
|
||||
BorshDeserialize,
|
||||
)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialOrd, Ord))]
|
||||
#[cfg_attr(any(feature = "host", test), derive(PartialOrd, Ord))]
|
||||
pub struct AccountId {
|
||||
value: [u8; 32],
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const DATA_MAX_LENGTH_IN_BYTES: usize = 100 * 1024; // 100 KiB
|
||||
|
||||
#[derive(Default, Clone, PartialEq, Eq, Serialize, BorshSerialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug))]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, BorshSerialize)]
|
||||
pub struct Data(Vec<u8>);
|
||||
|
||||
impl Data {
|
||||
|
||||
@@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Commitment, account::AccountId};
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, Hash))]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Clone, Hash))]
|
||||
pub struct NullifierPublicKey(pub [u8; 32]);
|
||||
|
||||
impl From<&NullifierPublicKey> for AccountId {
|
||||
|
||||
@@ -30,6 +30,20 @@ impl PdaSeed {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_authorized_pdas(
|
||||
caller_program_id: Option<ProgramId>,
|
||||
pda_seeds: &[PdaSeed],
|
||||
) -> HashSet<AccountId> {
|
||||
caller_program_id
|
||||
.map(|caller_program_id| {
|
||||
pda_seeds
|
||||
.iter()
|
||||
.map(|pda_seed| AccountId::from((&caller_program_id, pda_seed)))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
impl From<(&ProgramId, &PdaSeed)> for AccountId {
|
||||
fn from(value: (&ProgramId, &PdaSeed)) -> Self {
|
||||
use risc0_zkvm::sha::{Impl, Sha256};
|
||||
@@ -93,6 +107,13 @@ impl AccountPostState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a post state that requests ownership of the account
|
||||
/// if the account's program owner is the default program ID.
|
||||
pub fn new_claimed_if_default(account: Account) -> Self {
|
||||
let claim = account.program_owner == DEFAULT_PROGRAM_ID;
|
||||
Self { account, claim }
|
||||
}
|
||||
|
||||
/// Returns `true` if this post state requests that the account
|
||||
/// be claimed (owned) by the executing program.
|
||||
pub fn requires_claim(&self) -> bool {
|
||||
@@ -108,6 +129,11 @@ impl AccountPostState {
|
||||
pub fn account_mut(&mut self) -> &mut Account {
|
||||
&mut self.account
|
||||
}
|
||||
|
||||
/// Consumes the post state and returns the underlying account
|
||||
pub fn into_account(self) -> Account {
|
||||
self.account
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use nssa_core::{
|
||||
MembershipProof, NullifierPublicKey, NullifierSecretKey, PrivacyPreservingCircuitInput,
|
||||
PrivacyPreservingCircuitOutput, SharedSecretKey,
|
||||
account::AccountWithMetadata,
|
||||
program::{InstructionData, ProgramId, ProgramOutput},
|
||||
program::{ChainedCall, InstructionData, ProgramId, ProgramOutput},
|
||||
};
|
||||
use risc0_zkvm::{ExecutorEnv, InnerReceipt, Receipt, default_prover};
|
||||
|
||||
@@ -43,27 +43,44 @@ impl From<Program> for ProgramWithDependencies {
|
||||
}
|
||||
|
||||
/// Generates a proof of the execution of a NSSA program inside the privacy preserving execution
|
||||
/// circuit
|
||||
/// circuit.
|
||||
#[expect(clippy::too_many_arguments, reason = "TODO: fix later")]
|
||||
pub fn execute_and_prove(
|
||||
pre_states: &[AccountWithMetadata],
|
||||
instruction_data: &InstructionData,
|
||||
visibility_mask: &[u8],
|
||||
private_account_nonces: &[u128],
|
||||
private_account_keys: &[(NullifierPublicKey, SharedSecretKey)],
|
||||
private_account_nsks: &[NullifierSecretKey],
|
||||
private_account_membership_proofs: &[Option<MembershipProof>],
|
||||
pre_states: Vec<AccountWithMetadata>,
|
||||
instruction_data: InstructionData,
|
||||
visibility_mask: Vec<u8>,
|
||||
private_account_nonces: Vec<u128>,
|
||||
private_account_keys: Vec<(NullifierPublicKey, SharedSecretKey)>,
|
||||
private_account_nsks: Vec<NullifierSecretKey>,
|
||||
private_account_membership_proofs: Vec<Option<MembershipProof>>,
|
||||
program_with_dependencies: &ProgramWithDependencies,
|
||||
) -> Result<(PrivacyPreservingCircuitOutput, Proof), NssaError> {
|
||||
let mut program = &program_with_dependencies.program;
|
||||
let dependencies = &program_with_dependencies.dependencies;
|
||||
let mut instruction_data = instruction_data.clone();
|
||||
let mut pre_states = pre_states.to_vec();
|
||||
let ProgramWithDependencies {
|
||||
program,
|
||||
dependencies,
|
||||
} = program_with_dependencies;
|
||||
let mut env_builder = ExecutorEnv::builder();
|
||||
let mut program_outputs = Vec::new();
|
||||
|
||||
for _i in 0..MAX_NUMBER_CHAINED_CALLS {
|
||||
let inner_receipt = execute_and_prove_program(program, &pre_states, &instruction_data)?;
|
||||
let initial_call = ChainedCall {
|
||||
program_id: program.id(),
|
||||
instruction_data: instruction_data.clone(),
|
||||
pre_states,
|
||||
pda_seeds: vec![],
|
||||
};
|
||||
|
||||
let mut chained_calls = VecDeque::from_iter([(initial_call, program)]);
|
||||
let mut chain_calls_counter = 0;
|
||||
while let Some((chained_call, program)) = chained_calls.pop_front() {
|
||||
if chain_calls_counter >= MAX_NUMBER_CHAINED_CALLS {
|
||||
return Err(NssaError::MaxChainedCallsDepthExceeded);
|
||||
}
|
||||
|
||||
let inner_receipt = execute_and_prove_program(
|
||||
program,
|
||||
&chained_call.pre_states,
|
||||
&chained_call.instruction_data,
|
||||
)?;
|
||||
|
||||
let program_output: ProgramOutput = inner_receipt
|
||||
.journal
|
||||
@@ -76,39 +93,23 @@ pub fn execute_and_prove(
|
||||
// Prove circuit.
|
||||
env_builder.add_assumption(inner_receipt);
|
||||
|
||||
// TODO: Remove when multi-chain calls are supported in the circuit
|
||||
assert!(program_output.chained_calls.len() <= 1);
|
||||
// TODO: Modify when multi-chain calls are supported in the circuit
|
||||
if let Some(next_call) = program_output.chained_calls.first() {
|
||||
program = dependencies
|
||||
.get(&next_call.program_id)
|
||||
for new_call in program_output.chained_calls.into_iter().rev() {
|
||||
let next_program = dependencies
|
||||
.get(&new_call.program_id)
|
||||
.ok_or(NssaError::InvalidProgramBehavior)?;
|
||||
instruction_data = next_call.instruction_data.clone();
|
||||
// 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.account().clone();
|
||||
post_states_with_metadata.push(post_with_metadata);
|
||||
}
|
||||
|
||||
pre_states = next_call.pre_states.clone();
|
||||
} else {
|
||||
break;
|
||||
chained_calls.push_front((new_call, next_program));
|
||||
}
|
||||
|
||||
chain_calls_counter += 1;
|
||||
}
|
||||
|
||||
let circuit_input = PrivacyPreservingCircuitInput {
|
||||
program_outputs,
|
||||
visibility_mask: visibility_mask.to_vec(),
|
||||
private_account_nonces: private_account_nonces.to_vec(),
|
||||
private_account_keys: private_account_keys.to_vec(),
|
||||
private_account_nsks: private_account_nsks.to_vec(),
|
||||
private_account_membership_proofs: private_account_membership_proofs.to_vec(),
|
||||
visibility_mask,
|
||||
private_account_nonces,
|
||||
private_account_keys,
|
||||
private_account_nsks,
|
||||
private_account_membership_proofs,
|
||||
program_id: program_with_dependencies.program.id(),
|
||||
};
|
||||
|
||||
@@ -215,13 +216,13 @@ mod tests {
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
&[sender, recipient],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[0xdeadbeef],
|
||||
&[(recipient_keys.npk(), shared_secret)],
|
||||
&[],
|
||||
&[None],
|
||||
vec![sender, recipient],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![0, 2],
|
||||
vec![0xdeadbeef],
|
||||
vec![(recipient_keys.npk(), shared_secret)],
|
||||
vec![],
|
||||
vec![None],
|
||||
&Program::authenticated_transfer_program().into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -311,16 +312,16 @@ mod tests {
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
&[sender_pre.clone(), recipient],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![sender_pre.clone(), recipient],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(sender_keys.npk(), shared_secret_1),
|
||||
(recipient_keys.npk(), shared_secret_2),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[commitment_set.get_proof_for(&commitment_sender), None],
|
||||
vec![sender_keys.nsk],
|
||||
vec![commitment_set.get_proof_for(&commitment_sender), None],
|
||||
&program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -226,6 +226,15 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn changer_claimer() -> Self {
|
||||
use test_program_methods::{CHANGER_CLAIMER_ELF, CHANGER_CLAIMER_ID};
|
||||
|
||||
Program {
|
||||
id: CHANGER_CLAIMER_ID,
|
||||
elf: CHANGER_CLAIMER_ELF.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop() -> Self {
|
||||
use test_program_methods::{NOOP_ELF, NOOP_ID};
|
||||
|
||||
@@ -235,6 +244,17 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn malicious_authorization_changer() -> Self {
|
||||
use test_program_methods::{
|
||||
MALICIOUS_AUTHORIZATION_CHANGER_ELF, MALICIOUS_AUTHORIZATION_CHANGER_ID,
|
||||
};
|
||||
|
||||
Program {
|
||||
id: MALICIOUS_AUTHORIZATION_CHANGER_ID,
|
||||
elf: MALICIOUS_AUTHORIZATION_CHANGER_ELF.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modified_transfer_program() -> Self {
|
||||
use test_program_methods::MODIFIED_TRANSFER_ELF;
|
||||
// This unwrap won't panic since the `MODIFIED_TRANSFER_ELF` comes from risc0 build of
|
||||
|
||||
@@ -4,7 +4,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use log::debug;
|
||||
use nssa_core::{
|
||||
account::{Account, AccountId, AccountWithMetadata},
|
||||
program::{ChainedCall, DEFAULT_PROGRAM_ID, PdaSeed, ProgramId, validate_execution},
|
||||
program::{ChainedCall, DEFAULT_PROGRAM_ID, validate_execution},
|
||||
};
|
||||
use sha2::{Digest, digest::FixedOutput};
|
||||
|
||||
@@ -119,7 +119,7 @@ impl PublicTransaction {
|
||||
return Err(NssaError::MaxChainedCallsDepthExceeded);
|
||||
}
|
||||
|
||||
// Check the `program_id` corresponds to a deployed program
|
||||
// Check that 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()));
|
||||
};
|
||||
@@ -135,12 +135,14 @@ impl PublicTransaction {
|
||||
chained_call.program_id, program_output
|
||||
);
|
||||
|
||||
let authorized_pdas =
|
||||
self.compute_authorized_pdas(&caller_program_id, &chained_call.pda_seeds);
|
||||
let authorized_pdas = nssa_core::program::compute_authorized_pdas(
|
||||
caller_program_id,
|
||||
&chained_call.pda_seeds,
|
||||
);
|
||||
|
||||
for pre in &program_output.pre_states {
|
||||
let account_id = pre.account_id;
|
||||
// Check that the program output pre_states coinicide with the values in the public
|
||||
// Check that the program output pre_states coincide with the values in the public
|
||||
// state or with any modifications to those values during the chain of calls.
|
||||
let expected_pre = state_diff
|
||||
.get(&account_id)
|
||||
@@ -198,22 +200,23 @@ impl PublicTransaction {
|
||||
chain_calls_counter += 1;
|
||||
}
|
||||
|
||||
Ok(state_diff)
|
||||
}
|
||||
|
||||
fn compute_authorized_pdas(
|
||||
&self,
|
||||
caller_program_id: &Option<ProgramId>,
|
||||
pda_seeds: &[PdaSeed],
|
||||
) -> HashSet<AccountId> {
|
||||
if let Some(caller_program_id) = caller_program_id {
|
||||
pda_seeds
|
||||
.iter()
|
||||
.map(|pda_seed| AccountId::from((caller_program_id, pda_seed)))
|
||||
.collect()
|
||||
} else {
|
||||
HashSet::new()
|
||||
// Check that all modified uninitialized accounts where claimed
|
||||
for post in state_diff.iter().filter_map(|(account_id, post)| {
|
||||
let pre = state.get_account_by_id(account_id);
|
||||
if pre.program_owner != DEFAULT_PROGRAM_ID {
|
||||
return None;
|
||||
}
|
||||
if pre == *post {
|
||||
return None;
|
||||
}
|
||||
Some(post)
|
||||
}) {
|
||||
if post.program_owner == DEFAULT_PROGRAM_ID {
|
||||
return Err(NssaError::InvalidProgramBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(state_diff)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+389
-229
@@ -504,6 +504,7 @@ pub mod tests {
|
||||
self.insert_program(Program::chain_caller());
|
||||
self.insert_program(Program::amm());
|
||||
self.insert_program(Program::claimer());
|
||||
self.insert_program(Program::changer_claimer());
|
||||
self
|
||||
}
|
||||
|
||||
@@ -865,13 +866,13 @@ pub mod tests {
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender, recipient],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[0xdeadbeef],
|
||||
&[(recipient_keys.npk(), shared_secret)],
|
||||
&[],
|
||||
&[None],
|
||||
vec![sender, recipient],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![0, 2],
|
||||
vec![0xdeadbeef],
|
||||
vec![(recipient_keys.npk(), shared_secret)],
|
||||
vec![],
|
||||
vec![None],
|
||||
&Program::authenticated_transfer_program().into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -912,16 +913,16 @@ pub mod tests {
|
||||
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 2],
|
||||
&new_nonces,
|
||||
&[
|
||||
vec![sender_pre, recipient_pre],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![1, 2],
|
||||
new_nonces.to_vec(),
|
||||
vec![
|
||||
(sender_keys.npk(), shared_secret_1),
|
||||
(recipient_keys.npk(), shared_secret_2),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[state.get_proof_for_commitment(&sender_commitment), None],
|
||||
vec![sender_keys.nsk],
|
||||
vec![state.get_proof_for_commitment(&sender_commitment), None],
|
||||
&program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -965,13 +966,13 @@ pub mod tests {
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 0],
|
||||
&[new_nonce],
|
||||
&[(sender_keys.npk(), shared_secret)],
|
||||
&[sender_keys.nsk],
|
||||
&[state.get_proof_for_commitment(&sender_commitment)],
|
||||
vec![sender_pre, recipient_pre],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![1, 0],
|
||||
vec![new_nonce],
|
||||
vec![(sender_keys.npk(), shared_secret)],
|
||||
vec![sender_keys.nsk],
|
||||
vec![state.get_proof_for_commitment(&sender_commitment)],
|
||||
&program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1179,13 +1180,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1206,13 +1207,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1233,13 +1234,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(()).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(()).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1260,13 +1261,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(vec![0]).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(vec![0]).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1289,13 +1290,13 @@ pub mod tests {
|
||||
let large_data: Vec<u8> = vec![0; nssa_core::account::data::DATA_MAX_LENGTH_IN_BYTES + 1];
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(large_data).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(large_data).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.to_owned().into(),
|
||||
);
|
||||
|
||||
@@ -1316,13 +1317,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(()).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(()).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1352,13 +1353,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account_1, public_account_2],
|
||||
&Program::serialize_instruction(()).unwrap(),
|
||||
&[0, 0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account_1, public_account_2],
|
||||
Program::serialize_instruction(()).unwrap(),
|
||||
vec![0, 0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1379,13 +1380,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account],
|
||||
&Program::serialize_instruction(()).unwrap(),
|
||||
&[0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account],
|
||||
Program::serialize_instruction(()).unwrap(),
|
||||
vec![0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1415,13 +1416,13 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[public_account_1, public_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[0, 0],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account_1, public_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![0, 0],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1453,13 +1454,13 @@ pub mod tests {
|
||||
// Setting only one visibility mask for a circuit execution with two pre_state accounts.
|
||||
let visibility_mask = [0];
|
||||
let result = execute_and_prove(
|
||||
&[public_account_1, public_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&visibility_mask,
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account_1, public_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
visibility_mask.to_vec(),
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1486,11 +1487,11 @@ pub mod tests {
|
||||
// Setting only one nonce for an execution with two private accounts.
|
||||
let private_account_nonces = [0xdeadbeef1];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&private_account_nonces,
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
private_account_nonces.to_vec(),
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1500,8 +1501,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1530,13 +1531,13 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
)];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&private_account_keys,
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
private_account_keys.to_vec(),
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1563,11 +1564,11 @@ pub mod tests {
|
||||
// Setting no second commitment proof.
|
||||
let private_account_membership_proofs = [Some((0, vec![]))];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1577,8 +1578,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&private_account_membership_proofs,
|
||||
vec![sender_keys.nsk],
|
||||
private_account_membership_proofs.to_vec(),
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1605,11 +1606,11 @@ pub mod tests {
|
||||
// Setting no auth key for an execution with one non default private accounts.
|
||||
let private_account_nsks = [];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1619,8 +1620,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&private_account_nsks,
|
||||
&[],
|
||||
private_account_nsks.to_vec(),
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1663,13 +1664,13 @@ pub mod tests {
|
||||
let private_account_nsks = [recipient_keys.nsk];
|
||||
let private_account_membership_proofs = [Some((0, vec![]))];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&private_account_keys,
|
||||
&private_account_nsks,
|
||||
&private_account_membership_proofs,
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
private_account_keys.to_vec(),
|
||||
private_account_nsks.to_vec(),
|
||||
private_account_membership_proofs.to_vec(),
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1701,11 +1702,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1715,8 +1716,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1749,11 +1750,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1763,8 +1764,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1796,11 +1797,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1810,8 +1811,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1843,11 +1844,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1857,8 +1858,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1888,11 +1889,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1902,8 +1903,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1927,13 +1928,13 @@ pub mod tests {
|
||||
|
||||
let visibility_mask = [0, 3];
|
||||
let result = execute_and_prove(
|
||||
&[public_account_1, public_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&visibility_mask,
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
vec![public_account_1, public_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
visibility_mask.to_vec(),
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -1961,11 +1962,11 @@ pub mod tests {
|
||||
// accounts.
|
||||
let private_account_nonces = [0xdeadbeef1, 0xdeadbeef2, 0xdeadbeef3];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&private_account_nonces,
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
private_account_nonces.to_vec(),
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -1975,8 +1976,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -2017,13 +2018,13 @@ pub mod tests {
|
||||
),
|
||||
];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&private_account_keys,
|
||||
&[sender_keys.nsk],
|
||||
&[Some((0, vec![]))],
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
private_account_keys.to_vec(),
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -2053,11 +2054,11 @@ pub mod tests {
|
||||
let private_account_nsks = [sender_keys.nsk, recipient_keys.nsk];
|
||||
let private_account_membership_proofs = [Some((0, vec![])), Some((1, vec![]))];
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1, private_account_2],
|
||||
&Program::serialize_instruction(10u128).unwrap(),
|
||||
&visibility_mask,
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1, private_account_2],
|
||||
Program::serialize_instruction(10u128).unwrap(),
|
||||
visibility_mask.to_vec(),
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
@@ -2067,8 +2068,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&private_account_nsks,
|
||||
&private_account_membership_proofs,
|
||||
private_account_nsks.to_vec(),
|
||||
private_account_membership_proofs.to_vec(),
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -2149,16 +2150,16 @@ pub mod tests {
|
||||
let private_account_membership_proofs = [Some((1, vec![])), Some((1, vec![]))];
|
||||
let shared_secret = SharedSecretKey::new(&[55; 32], &sender_keys.ivk());
|
||||
let result = execute_and_prove(
|
||||
&[private_account_1.clone(), private_account_1],
|
||||
&Program::serialize_instruction(100u128).unwrap(),
|
||||
&visibility_mask,
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![private_account_1.clone(), private_account_1],
|
||||
Program::serialize_instruction(100u128).unwrap(),
|
||||
visibility_mask.to_vec(),
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(sender_keys.npk(), shared_secret),
|
||||
(sender_keys.npk(), shared_secret),
|
||||
],
|
||||
&private_account_nsks,
|
||||
&private_account_membership_proofs,
|
||||
private_account_nsks.to_vec(),
|
||||
private_account_membership_proofs.to_vec(),
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@@ -3941,8 +3942,9 @@ pub mod tests {
|
||||
assert_eq!(to_post, expected_to_post);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_chained_call() {
|
||||
#[test_case::test_case(1; "single call")]
|
||||
#[test_case::test_case(2; "two calls")]
|
||||
fn test_private_chained_call(number_of_calls: u32) {
|
||||
// Arrange
|
||||
let chain_caller = Program::chain_caller();
|
||||
let auth_transfers = Program::authenticated_transfer_program();
|
||||
@@ -3978,7 +3980,7 @@ pub mod tests {
|
||||
let instruction: (u128, ProgramId, u32, Option<PdaSeed>) = (
|
||||
amount,
|
||||
Program::authenticated_transfer_program().id(),
|
||||
1,
|
||||
number_of_calls,
|
||||
None,
|
||||
);
|
||||
|
||||
@@ -3999,14 +4001,14 @@ pub mod tests {
|
||||
let to_new_nonce = 0xdeadbeef2;
|
||||
|
||||
let from_expected_post = Account {
|
||||
balance: initial_balance - amount,
|
||||
balance: initial_balance - number_of_calls as u128 * amount,
|
||||
nonce: from_new_nonce,
|
||||
..from_account.account.clone()
|
||||
};
|
||||
let from_expected_commitment = Commitment::new(&from_keys.npk(), &from_expected_post);
|
||||
|
||||
let to_expected_post = Account {
|
||||
balance: amount,
|
||||
balance: number_of_calls as u128 * amount,
|
||||
nonce: to_new_nonce,
|
||||
..to_account.account.clone()
|
||||
};
|
||||
@@ -4014,13 +4016,13 @@ pub mod tests {
|
||||
|
||||
// Act
|
||||
let (output, proof) = execute_and_prove(
|
||||
&[to_account, from_account],
|
||||
&Program::serialize_instruction(instruction).unwrap(),
|
||||
&[1, 1],
|
||||
&[from_new_nonce, to_new_nonce],
|
||||
&[(from_keys.npk(), to_ss), (to_keys.npk(), from_ss)],
|
||||
&[from_keys.nsk, to_keys.nsk],
|
||||
&[
|
||||
vec![to_account, from_account],
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
vec![1, 1],
|
||||
vec![from_new_nonce, to_new_nonce],
|
||||
vec![(from_keys.npk(), to_ss), (to_keys.npk(), from_ss)],
|
||||
vec![from_keys.nsk, to_keys.nsk],
|
||||
vec![
|
||||
state.get_proof_for_commitment(&from_commitment),
|
||||
state.get_proof_for_commitment(&to_commitment),
|
||||
],
|
||||
@@ -4255,13 +4257,13 @@ pub mod tests {
|
||||
|
||||
// Execute and prove the circuit with the authorized account but no commitment proof
|
||||
let (output, proof) = execute_and_prove(
|
||||
std::slice::from_ref(&authorized_account),
|
||||
&Program::serialize_instruction(balance).unwrap(),
|
||||
&[1],
|
||||
&[nonce],
|
||||
&[(private_keys.npk(), shared_secret)],
|
||||
&[private_keys.nsk],
|
||||
&[None],
|
||||
vec![authorized_account],
|
||||
Program::serialize_instruction(balance).unwrap(),
|
||||
vec![1],
|
||||
vec![nonce],
|
||||
vec![(private_keys.npk(), shared_secret)],
|
||||
vec![private_keys.nsk],
|
||||
vec![None],
|
||||
&program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -4308,13 +4310,13 @@ pub mod tests {
|
||||
|
||||
// Step 2: Execute claimer program to claim the account with authentication
|
||||
let (output, proof) = execute_and_prove(
|
||||
std::slice::from_ref(&authorized_account),
|
||||
&Program::serialize_instruction(balance).unwrap(),
|
||||
&[1],
|
||||
&[nonce],
|
||||
&[(private_keys.npk(), shared_secret)],
|
||||
&[private_keys.nsk],
|
||||
&[None],
|
||||
vec![authorized_account.clone()],
|
||||
Program::serialize_instruction(balance).unwrap(),
|
||||
vec![1],
|
||||
vec![nonce],
|
||||
vec![(private_keys.npk(), shared_secret)],
|
||||
vec![private_keys.nsk],
|
||||
vec![None],
|
||||
&claimer_program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -4356,16 +4358,174 @@ pub mod tests {
|
||||
|
||||
// Step 3: Try to execute noop program with authentication but without initialization
|
||||
let res = execute_and_prove(
|
||||
std::slice::from_ref(&account_metadata),
|
||||
&Program::serialize_instruction(()).unwrap(),
|
||||
&[1],
|
||||
&[nonce2],
|
||||
&[(private_keys.npk(), shared_secret2)],
|
||||
&[private_keys.nsk],
|
||||
&[None],
|
||||
vec![account_metadata],
|
||||
Program::serialize_instruction(()).unwrap(),
|
||||
vec![1],
|
||||
vec![nonce2],
|
||||
vec![(private_keys.npk(), shared_secret2)],
|
||||
vec![private_keys.nsk],
|
||||
vec![None],
|
||||
&noop_program.into(),
|
||||
);
|
||||
|
||||
assert!(matches!(res, Err(NssaError::CircuitProvingError(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_changer_claimer_no_data_change_no_claim_succeeds() {
|
||||
let initial_data = [];
|
||||
let mut state =
|
||||
V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs();
|
||||
let account_id = AccountId::new([1; 32]);
|
||||
let program_id = Program::changer_claimer().id();
|
||||
// Don't change data (None) and don't claim (false)
|
||||
let instruction: (Option<Vec<u8>>, bool) = (None, false);
|
||||
|
||||
let message =
|
||||
public_transaction::Message::try_new(program_id, vec![account_id], vec![], instruction)
|
||||
.unwrap();
|
||||
let witness_set = public_transaction::WitnessSet::for_message(&message, &[]);
|
||||
let tx = PublicTransaction::new(message, witness_set);
|
||||
|
||||
let result = state.transition_from_public_transaction(&tx);
|
||||
|
||||
// Should succeed - no changes made, no claim needed
|
||||
assert!(result.is_ok());
|
||||
// Account should remain default/unclaimed
|
||||
assert_eq!(state.get_account_by_id(&account_id), Account::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_changer_claimer_data_change_no_claim_fails() {
|
||||
let initial_data = [];
|
||||
let mut state =
|
||||
V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs();
|
||||
let account_id = AccountId::new([1; 32]);
|
||||
let program_id = Program::changer_claimer().id();
|
||||
// Change data but don't claim (false) - should fail
|
||||
let new_data = vec![1, 2, 3, 4, 5];
|
||||
let instruction: (Option<Vec<u8>>, bool) = (Some(new_data), false);
|
||||
|
||||
let message =
|
||||
public_transaction::Message::try_new(program_id, vec![account_id], vec![], instruction)
|
||||
.unwrap();
|
||||
let witness_set = public_transaction::WitnessSet::for_message(&message, &[]);
|
||||
let tx = PublicTransaction::new(message, witness_set);
|
||||
|
||||
let result = state.transition_from_public_transaction(&tx);
|
||||
|
||||
// Should fail - cannot modify data without claiming the account
|
||||
assert!(matches!(result, Err(NssaError::InvalidProgramBehavior)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_changer_claimer_no_data_change_no_claim_succeeds() {
|
||||
let program = Program::changer_claimer();
|
||||
let sender_keys = test_private_account_keys_1();
|
||||
let private_account =
|
||||
AccountWithMetadata::new(Account::default(), true, &sender_keys.npk());
|
||||
// Don't change data (None) and don't claim (false)
|
||||
let instruction: (Option<Vec<u8>>, bool) = (None, false);
|
||||
|
||||
let result = execute_and_prove(
|
||||
vec![private_account],
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
vec![1],
|
||||
vec![2],
|
||||
vec![(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
|
||||
)],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
// Should succeed - no changes made, no claim needed
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_changer_claimer_data_change_no_claim_fails() {
|
||||
let program = Program::changer_claimer();
|
||||
let sender_keys = test_private_account_keys_1();
|
||||
let private_account =
|
||||
AccountWithMetadata::new(Account::default(), true, &sender_keys.npk());
|
||||
// Change data but don't claim (false) - should fail
|
||||
let new_data = vec![1, 2, 3, 4, 5];
|
||||
let instruction: (Option<Vec<u8>>, bool) = (Some(new_data), false);
|
||||
|
||||
let result = execute_and_prove(
|
||||
vec![private_account],
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
vec![1],
|
||||
vec![2],
|
||||
vec![(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
|
||||
)],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
// Should fail - cannot modify data without claiming the account
|
||||
assert!(matches!(result, Err(NssaError::CircuitProvingError(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_malicious_authorization_changer_should_fail_in_privacy_preserving_circuit() {
|
||||
// Arrange
|
||||
let malicious_program = Program::malicious_authorization_changer();
|
||||
let auth_transfers = Program::authenticated_transfer_program();
|
||||
let sender_keys = test_public_account_keys_1();
|
||||
let recipient_keys = test_private_account_keys_1();
|
||||
|
||||
let sender_account = AccountWithMetadata::new(
|
||||
Account {
|
||||
program_owner: auth_transfers.id(),
|
||||
balance: 100,
|
||||
..Default::default()
|
||||
},
|
||||
false,
|
||||
sender_keys.account_id(),
|
||||
);
|
||||
let recipient_account =
|
||||
AccountWithMetadata::new(Account::default(), true, &recipient_keys.npk());
|
||||
|
||||
let recipient_commitment =
|
||||
Commitment::new(&recipient_keys.npk(), &recipient_account.account);
|
||||
let state = V02State::new_with_genesis_accounts(
|
||||
&[(sender_account.account_id, sender_account.account.balance)],
|
||||
std::slice::from_ref(&recipient_commitment),
|
||||
)
|
||||
.with_test_programs();
|
||||
|
||||
let balance_to_transfer = 10u128;
|
||||
let instruction = (balance_to_transfer, auth_transfers.id());
|
||||
|
||||
let recipient_esk = [3; 32];
|
||||
let recipient = SharedSecretKey::new(&recipient_esk, &recipient_keys.ivk());
|
||||
|
||||
let mut dependencies = HashMap::new();
|
||||
dependencies.insert(auth_transfers.id(), auth_transfers);
|
||||
let program_with_deps = ProgramWithDependencies::new(malicious_program, dependencies);
|
||||
|
||||
let recipient_new_nonce = 0xdeadbeef1;
|
||||
|
||||
// Act - execute the malicious program - this should fail during proving
|
||||
let result = execute_and_prove(
|
||||
vec![sender_account, recipient_account],
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
vec![0, 1],
|
||||
vec![recipient_new_nonce],
|
||||
vec![(recipient_keys.npk(), recipient)],
|
||||
vec![recipient_keys.nsk],
|
||||
vec![state.get_proof_for_commitment(&recipient_commitment)],
|
||||
&program_with_deps,
|
||||
);
|
||||
|
||||
// Assert - should fail because the malicious program tries to manipulate is_authorized
|
||||
assert!(matches!(result, Err(NssaError::CircuitProvingError(_))));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user