mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-09 08:43:12 +00:00
Merge 5c965deb56ae0827f97562cbe2ee134c709120ee into 1d09afd9e004953a7218fe02d4e897cc45c67465
This commit is contained in:
commit
d1578c6213
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -2670,6 +2670,7 @@ dependencies = [
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"sha2",
|
||||
"test-case",
|
||||
"test_program_methods",
|
||||
"thiserror",
|
||||
]
|
||||
@ -4310,6 +4311,39 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-core"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_program_methods"
|
||||
version = "0.1.0"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -53,7 +53,7 @@ async fn main() {
|
||||
wallet_core
|
||||
.send_privacy_preserving_tx(
|
||||
accounts,
|
||||
&Program::serialize_instruction(greeting).unwrap(),
|
||||
Program::serialize_instruction(greeting).unwrap(),
|
||||
&program.into(),
|
||||
)
|
||||
.await
|
||||
|
||||
@ -61,7 +61,7 @@ async fn main() {
|
||||
wallet_core
|
||||
.send_privacy_preserving_tx(
|
||||
accounts,
|
||||
&Program::serialize_instruction(instruction).unwrap(),
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
&program_with_dependencies,
|
||||
)
|
||||
.await
|
||||
|
||||
@ -104,7 +104,7 @@ async fn main() {
|
||||
wallet_core
|
||||
.send_privacy_preserving_tx(
|
||||
accounts,
|
||||
&Program::serialize_instruction(instruction).unwrap(),
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
&program.into(),
|
||||
)
|
||||
.await
|
||||
@ -145,7 +145,7 @@ async fn main() {
|
||||
wallet_core
|
||||
.send_privacy_preserving_tx(
|
||||
accounts,
|
||||
&Program::serialize_instruction(instruction).unwrap(),
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
&program.into(),
|
||||
)
|
||||
.await
|
||||
|
||||
@ -159,16 +159,16 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
]],
|
||||
);
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
vec![sender_pre, recipient_pre],
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![0xdeadbeef1, 0xdeadbeef2],
|
||||
vec![
|
||||
(sender_npk.clone(), sender_ss),
|
||||
(recipient_npk.clone(), recipient_ss),
|
||||
],
|
||||
&[sender_nsk],
|
||||
&[Some(proof)],
|
||||
vec![sender_nsk],
|
||||
vec![Some(proof)],
|
||||
&program.into(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -108,6 +108,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};
|
||||
|
||||
@ -46,69 +46,72 @@ impl From<Program> for ProgramWithDependencies {
|
||||
/// 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
|
||||
.decode()
|
||||
.map_err(|e| NssaError::ProgramOutputDeserializationError(e.to_string()))?;
|
||||
|
||||
// TODO: Why private execution doesn't care about public account authorization?
|
||||
|
||||
// TODO: remove clone
|
||||
program_outputs.push(program_output.clone());
|
||||
|
||||
// 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 +218,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 +314,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();
|
||||
|
||||
@ -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()));
|
||||
};
|
||||
@ -136,11 +136,11 @@ impl PublicTransaction {
|
||||
);
|
||||
|
||||
let authorized_pdas =
|
||||
self.compute_authorized_pdas(&caller_program_id, &chained_call.pda_seeds);
|
||||
Self::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)
|
||||
@ -202,7 +202,6 @@ impl PublicTransaction {
|
||||
}
|
||||
|
||||
fn compute_authorized_pdas(
|
||||
&self,
|
||||
caller_program_id: &Option<ProgramId>,
|
||||
pda_seeds: &[PdaSeed],
|
||||
) -> HashSet<AccountId> {
|
||||
|
||||
@ -865,13 +865,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 +912,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 +965,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 +1179,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 +1206,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 +1233,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 +1260,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 +1289,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 +1316,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 +1352,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 +1379,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 +1415,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 +1453,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 +1486,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 +1500,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 +1530,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 +1563,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 +1577,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 +1605,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 +1619,8 @@ pub mod tests {
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
),
|
||||
],
|
||||
&private_account_nsks,
|
||||
&[],
|
||||
private_account_nsks.to_vec(),
|
||||
vec![],
|
||||
&program.into(),
|
||||
);
|
||||
|
||||
@ -1663,13 +1663,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 +1701,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 +1715,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 +1749,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 +1763,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 +1796,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 +1810,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 +1843,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 +1857,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 +1888,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 +1902,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 +1927,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 +1961,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 +1975,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 +2017,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 +2053,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 +2067,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 +2149,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 +3941,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 +3979,7 @@ pub mod tests {
|
||||
let instruction: (u128, ProgramId, u32, Option<PdaSeed>) = (
|
||||
amount,
|
||||
Program::authenticated_transfer_program().id(),
|
||||
1,
|
||||
number_of_calls,
|
||||
None,
|
||||
);
|
||||
|
||||
@ -3999,14 +4000,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 +4015,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 +4256,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 +4309,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,13 +4357,13 @@ 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(),
|
||||
);
|
||||
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
convert::Infallible,
|
||||
};
|
||||
|
||||
use nssa_core::{
|
||||
Commitment, CommitmentSetDigest, DUMMY_COMMITMENT_HASH, EncryptionScheme, Nullifier,
|
||||
NullifierPublicKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, AccountId, AccountWithMetadata},
|
||||
Commitment, CommitmentSetDigest, DUMMY_COMMITMENT_HASH, EncryptionScheme, MembershipProof,
|
||||
Nullifier, NullifierPublicKey, NullifierSecretKey, PrivacyPreservingCircuitInput,
|
||||
PrivacyPreservingCircuitOutput, SharedSecretKey,
|
||||
account::{Account, AccountId, AccountWithMetadata, Nonce},
|
||||
compute_digest_for_path,
|
||||
encryption::Ciphertext,
|
||||
program::{DEFAULT_PROGRAM_ID, MAX_NUMBER_CHAINED_CALLS, validate_execution},
|
||||
program::{
|
||||
ChainedCall, DEFAULT_PROGRAM_ID, MAX_NUMBER_CHAINED_CALLS, ProgramId, ProgramOutput,
|
||||
validate_execution,
|
||||
},
|
||||
};
|
||||
use risc0_zkvm::{guest::env, serde::to_vec};
|
||||
|
||||
@ -18,118 +24,172 @@ fn main() {
|
||||
private_account_keys,
|
||||
private_account_nsks,
|
||||
private_account_membership_proofs,
|
||||
mut program_id,
|
||||
program_id,
|
||||
} = env::read();
|
||||
|
||||
let mut pre_states: Vec<AccountWithMetadata> = Vec::new();
|
||||
let mut state_diff: HashMap<AccountId, Account> = HashMap::new();
|
||||
let execution_state = ExecutionState::derive_from_outputs(program_id, program_outputs);
|
||||
|
||||
let num_calls = program_outputs.len();
|
||||
if num_calls > MAX_NUMBER_CHAINED_CALLS {
|
||||
panic!("Max chained calls depth is exceeded");
|
||||
let output = compute_circuit_output(
|
||||
execution_state,
|
||||
&visibility_mask,
|
||||
&private_account_nonces,
|
||||
&private_account_keys,
|
||||
&private_account_nsks,
|
||||
&private_account_membership_proofs,
|
||||
);
|
||||
|
||||
env::commit(&output);
|
||||
}
|
||||
|
||||
/// World state before and after program execution.
|
||||
struct ExecutionState {
|
||||
pre_states: Vec<AccountWithMetadata>,
|
||||
post_states: HashMap<AccountId, Account>,
|
||||
}
|
||||
|
||||
impl ExecutionState {
|
||||
/// Validate program outputs and derive the overall execution state.
|
||||
pub fn derive_from_outputs(program_id: ProgramId, program_outputs: Vec<ProgramOutput>) -> Self {
|
||||
let Some(first_output) = program_outputs.first() else {
|
||||
panic!("Program outputs is empty")
|
||||
};
|
||||
|
||||
let initial_call = ChainedCall {
|
||||
program_id,
|
||||
instruction_data: first_output.instruction_data.clone(),
|
||||
pre_states: first_output.pre_states.clone(),
|
||||
pda_seeds: Vec::new(),
|
||||
};
|
||||
let mut chained_calls = VecDeque::from_iter([initial_call]);
|
||||
|
||||
let mut execution_state = ExecutionState {
|
||||
pre_states: Vec::new(),
|
||||
post_states: HashMap::new(),
|
||||
};
|
||||
let mut last_program_id = program_id;
|
||||
let mut program_outputs_iter = program_outputs.into_iter();
|
||||
let mut chain_calls_counter = 0;
|
||||
while let Some(chained_call) = chained_calls.pop_front() {
|
||||
assert!(
|
||||
chain_calls_counter <= MAX_NUMBER_CHAINED_CALLS,
|
||||
"Max chained calls depth is exceeded"
|
||||
);
|
||||
|
||||
let Some(program_output) = program_outputs_iter.next() else {
|
||||
panic!("Insufficient program outputs for chained calls");
|
||||
};
|
||||
|
||||
// Check that instruction data in chained call is the instruction data in program output
|
||||
assert_eq!(
|
||||
chained_call.instruction_data, program_output.instruction_data,
|
||||
"Mismatched instruction data between chained call and program output"
|
||||
);
|
||||
|
||||
// Check that `program_output` is consistent with the execution of the corresponding
|
||||
// program.
|
||||
let program_output_words =
|
||||
&to_vec(&program_output).expect("program_output must be serializable");
|
||||
env::verify(chained_call.program_id, program_output_words).unwrap_or_else(
|
||||
|_: Infallible| unreachable!("Infallible error is never constructed"),
|
||||
);
|
||||
|
||||
// TODO: Why private execution doesn't care about public account authorization?
|
||||
|
||||
// Check that the program is well behaved.
|
||||
// See the # Programs section for the definition of the `validate_execution` method.
|
||||
let execution_valid = validate_execution(
|
||||
&program_output.pre_states,
|
||||
&program_output.post_states,
|
||||
chained_call.program_id,
|
||||
);
|
||||
assert!(execution_valid, "Bad behaved program");
|
||||
|
||||
for next_call in program_output.chained_calls.iter().rev() {
|
||||
chained_calls.push_front(next_call.clone());
|
||||
}
|
||||
|
||||
execution_state.populate_from_output(chained_call.program_id, program_output);
|
||||
last_program_id = chained_call.program_id;
|
||||
chain_calls_counter += 1;
|
||||
}
|
||||
|
||||
assert!(
|
||||
program_outputs_iter.next().is_none(),
|
||||
"Inner call without a chained call found",
|
||||
);
|
||||
|
||||
// Claim accounts
|
||||
for account in execution_state.post_states.values_mut() {
|
||||
if account.program_owner == DEFAULT_PROGRAM_ID {
|
||||
account.program_owner = last_program_id;
|
||||
}
|
||||
}
|
||||
|
||||
execution_state
|
||||
}
|
||||
|
||||
let Some(last_program_call) = program_outputs.last() else {
|
||||
panic!("Program outputs is empty")
|
||||
fn populate_from_output(&mut self, program_id: ProgramId, program_output: ProgramOutput) {
|
||||
for (pre, mut post) in program_output
|
||||
.pre_states
|
||||
.into_iter()
|
||||
.zip(program_output.post_states)
|
||||
{
|
||||
let pre_account_id = pre.account_id;
|
||||
if let Some(account_pre) = self.post_states.get(&pre_account_id) {
|
||||
assert_eq!(account_pre, &pre.account, "Inconsistent pre state");
|
||||
} else {
|
||||
self.pre_states.push(pre);
|
||||
}
|
||||
|
||||
if post.requires_claim() {
|
||||
// The invoked program can only claim accounts with default program id.
|
||||
if post.account().program_owner == DEFAULT_PROGRAM_ID {
|
||||
post.account_mut().program_owner = program_id;
|
||||
} else {
|
||||
panic!("Cannot claim an initialized account")
|
||||
}
|
||||
}
|
||||
|
||||
self.post_states.insert(pre_account_id, post.into_account());
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an iterator over pre and post states of each account involved in the execution.
|
||||
pub fn into_states_iter(
|
||||
mut self,
|
||||
) -> impl ExactSizeIterator<Item = (AccountWithMetadata, Account)> {
|
||||
self.pre_states.into_iter().map(move |pre| {
|
||||
let post = self
|
||||
.post_states
|
||||
.remove(&pre.account_id)
|
||||
.expect("Account from pre states should exist in state diff");
|
||||
(pre, post)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_circuit_output(
|
||||
execution_state: ExecutionState,
|
||||
visibility_mask: &[u8],
|
||||
private_account_nonces: &[Nonce],
|
||||
private_account_keys: &[(NullifierPublicKey, SharedSecretKey)],
|
||||
private_account_nsks: &[NullifierSecretKey],
|
||||
private_account_membership_proofs: &[Option<MembershipProof>],
|
||||
) -> PrivacyPreservingCircuitOutput {
|
||||
let mut output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states: Vec::new(),
|
||||
public_post_states: Vec::new(),
|
||||
ciphertexts: Vec::new(),
|
||||
new_commitments: Vec::new(),
|
||||
new_nullifiers: Vec::new(),
|
||||
};
|
||||
|
||||
if !last_program_call.chained_calls.is_empty() {
|
||||
panic!("Call stack is incomplete");
|
||||
}
|
||||
|
||||
for window in program_outputs.windows(2) {
|
||||
let caller = &window[0];
|
||||
let callee = &window[1];
|
||||
|
||||
if caller.chained_calls.len() > 1 {
|
||||
panic!("Privacy Multi-chained calls are not supported yet");
|
||||
}
|
||||
|
||||
// TODO: Modify when multi-chain calls are supported in the circuit
|
||||
let Some(caller_chained_call) = &caller.chained_calls.first() else {
|
||||
panic!("Expected chained call");
|
||||
};
|
||||
|
||||
// Check that instruction data in caller is the instruction data in callee
|
||||
if caller_chained_call.instruction_data != callee.instruction_data {
|
||||
panic!("Invalid instruction data");
|
||||
}
|
||||
|
||||
// Check that account pre_states in caller are the ones in calle
|
||||
if caller_chained_call.pre_states != callee.pre_states {
|
||||
panic!("Invalid pre states");
|
||||
}
|
||||
}
|
||||
|
||||
for (i, program_output) in program_outputs.iter().enumerate() {
|
||||
let mut program_output = program_output.clone();
|
||||
|
||||
// Check that `program_output` is consistent with the execution of the corresponding
|
||||
// program.
|
||||
let program_output_words =
|
||||
&to_vec(&program_output).expect("program_output must be serializable");
|
||||
env::verify(program_id, program_output_words)
|
||||
.expect("program output must match the program's execution");
|
||||
|
||||
// Check that the program is well behaved.
|
||||
// See the # Programs section for the definition of the `validate_execution` method.
|
||||
if !validate_execution(
|
||||
&program_output.pre_states,
|
||||
&program_output.post_states,
|
||||
program_id,
|
||||
) {
|
||||
panic!("Bad behaved program");
|
||||
}
|
||||
|
||||
// The invoked program claims the accounts with default program id.
|
||||
for post in program_output
|
||||
.post_states
|
||||
.iter_mut()
|
||||
.filter(|post| post.requires_claim())
|
||||
{
|
||||
// The invoked program can only claim accounts with default program id.
|
||||
if post.account().program_owner == DEFAULT_PROGRAM_ID {
|
||||
post.account_mut().program_owner = program_id;
|
||||
} else {
|
||||
panic!("Cannot claim an initialized account")
|
||||
}
|
||||
}
|
||||
|
||||
for (pre, post) in program_output
|
||||
.pre_states
|
||||
.iter()
|
||||
.zip(&program_output.post_states)
|
||||
{
|
||||
if let Some(account_pre) = state_diff.get(&pre.account_id) {
|
||||
if account_pre != &pre.account {
|
||||
panic!("Invalid input");
|
||||
}
|
||||
} else {
|
||||
pre_states.push(pre.clone());
|
||||
}
|
||||
state_diff.insert(pre.account_id, post.account().clone());
|
||||
}
|
||||
|
||||
// TODO: Modify when multi-chain calls are supported in the circuit
|
||||
if let Some(next_chained_call) = &program_output.chained_calls.first() {
|
||||
program_id = next_chained_call.program_id;
|
||||
} else if i != program_outputs.len() - 1 {
|
||||
panic!("Inner call without a chained call found")
|
||||
};
|
||||
}
|
||||
|
||||
let n_accounts = pre_states.len();
|
||||
if visibility_mask.len() != n_accounts {
|
||||
panic!("Invalid visibility mask length");
|
||||
}
|
||||
|
||||
// These lists will be the public outputs of this circuit
|
||||
// and will be populated next.
|
||||
let mut public_pre_states: Vec<AccountWithMetadata> = Vec::new();
|
||||
let mut public_post_states: Vec<Account> = Vec::new();
|
||||
let mut ciphertexts: Vec<Ciphertext> = Vec::new();
|
||||
let mut new_commitments: Vec<Commitment> = Vec::new();
|
||||
let mut new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)> = Vec::new();
|
||||
let states_iter = execution_state.into_states_iter();
|
||||
assert_eq!(
|
||||
visibility_mask.len(),
|
||||
states_iter.len(),
|
||||
"Invalid visibility mask length"
|
||||
);
|
||||
|
||||
let mut private_nonces_iter = private_account_nonces.iter();
|
||||
let mut private_keys_iter = private_account_keys.iter();
|
||||
@ -137,141 +197,156 @@ fn main() {
|
||||
let mut private_membership_proofs_iter = private_account_membership_proofs.iter();
|
||||
|
||||
let mut output_index = 0;
|
||||
for i in 0..n_accounts {
|
||||
match visibility_mask[i] {
|
||||
for (visibility_mask, (pre_state, post_state)) in
|
||||
visibility_mask.iter().copied().zip(states_iter)
|
||||
{
|
||||
match visibility_mask {
|
||||
0 => {
|
||||
// Public account
|
||||
public_pre_states.push(pre_states[i].clone());
|
||||
|
||||
let mut post = state_diff.get(&pre_states[i].account_id).unwrap().clone();
|
||||
|
||||
if post.program_owner == DEFAULT_PROGRAM_ID {
|
||||
// Claim account
|
||||
post.program_owner = program_id;
|
||||
}
|
||||
public_post_states.push(post);
|
||||
output.public_pre_states.push(pre_state);
|
||||
output.public_post_states.push(post_state);
|
||||
}
|
||||
1 | 2 => {
|
||||
let new_nonce = private_nonces_iter.next().expect("Missing private nonce");
|
||||
let (npk, shared_secret) = private_keys_iter.next().expect("Missing keys");
|
||||
let Some((npk, shared_secret)) = private_keys_iter.next() else {
|
||||
panic!("Missing private account key");
|
||||
};
|
||||
|
||||
if AccountId::from(npk) != pre_states[i].account_id {
|
||||
panic!("AccountId mismatch");
|
||||
}
|
||||
assert_eq!(
|
||||
AccountId::from(npk),
|
||||
pre_state.account_id,
|
||||
"AccountId mismatch"
|
||||
);
|
||||
|
||||
if visibility_mask[i] == 1 {
|
||||
let new_nullifier = if visibility_mask == 1 {
|
||||
// Private account with authentication
|
||||
let nsk = private_nsks_iter.next().expect("Missing nsk");
|
||||
|
||||
let Some(nsk) = private_nsks_iter.next() else {
|
||||
panic!("Missing private account nullifier secret key");
|
||||
};
|
||||
|
||||
// Verify the nullifier public key
|
||||
let expected_npk = NullifierPublicKey::from(nsk);
|
||||
if &expected_npk != npk {
|
||||
panic!("Nullifier public key mismatch");
|
||||
}
|
||||
assert_eq!(
|
||||
npk,
|
||||
&NullifierPublicKey::from(nsk),
|
||||
"Nullifier public key mismatch"
|
||||
);
|
||||
|
||||
// Check pre_state authorization
|
||||
if !pre_states[i].is_authorized {
|
||||
panic!("Pre-state not authorized");
|
||||
}
|
||||
assert!(
|
||||
pre_state.is_authorized,
|
||||
"Pre-state not authorized for authenticated private account"
|
||||
);
|
||||
|
||||
let membership_proof_opt = private_membership_proofs_iter
|
||||
.next()
|
||||
.expect("Missing membership proof");
|
||||
let (nullifier, set_digest) = membership_proof_opt
|
||||
.as_ref()
|
||||
.map(|membership_proof| {
|
||||
// Compute commitment set digest associated with provided auth path
|
||||
let commitment_pre = Commitment::new(npk, &pre_states[i].account);
|
||||
let set_digest =
|
||||
compute_digest_for_path(&commitment_pre, membership_proof);
|
||||
let Some(membership_proof_opt) = private_membership_proofs_iter.next() else {
|
||||
panic!("Missing membership proof");
|
||||
};
|
||||
|
||||
// Compute update nullifier
|
||||
let nullifier = Nullifier::for_account_update(&commitment_pre, nsk);
|
||||
(nullifier, set_digest)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
if pre_states[i].account != Account::default() {
|
||||
panic!("Found new private account with non default values.");
|
||||
}
|
||||
|
||||
// Compute initialization nullifier
|
||||
let nullifier = Nullifier::for_account_initialization(npk);
|
||||
(nullifier, DUMMY_COMMITMENT_HASH)
|
||||
});
|
||||
new_nullifiers.push((nullifier, set_digest));
|
||||
compute_nullifier_and_set_digest(
|
||||
membership_proof_opt.as_ref(),
|
||||
&pre_state.account,
|
||||
npk,
|
||||
nsk,
|
||||
)
|
||||
} else {
|
||||
// Private account without authentication
|
||||
if pre_states[i].account != Account::default() {
|
||||
panic!("Found new private account with non default values.");
|
||||
}
|
||||
|
||||
if pre_states[i].is_authorized {
|
||||
panic!("Found new private account marked as authorized.");
|
||||
}
|
||||
assert_eq!(
|
||||
pre_state.account,
|
||||
Account::default(),
|
||||
"Found new private account with non default values",
|
||||
);
|
||||
|
||||
assert!(
|
||||
!pre_state.is_authorized,
|
||||
"Found new private account marked as authorized."
|
||||
);
|
||||
|
||||
let Some(membership_proof_opt) = private_membership_proofs_iter.next() else {
|
||||
panic!("Missing membership proof");
|
||||
};
|
||||
|
||||
let membership_proof_opt = private_membership_proofs_iter
|
||||
.next()
|
||||
.expect("Missing membership proof");
|
||||
assert!(
|
||||
membership_proof_opt.is_none(),
|
||||
"Membership proof must be None for unauthorized accounts"
|
||||
);
|
||||
|
||||
let nullifier = Nullifier::for_account_initialization(npk);
|
||||
new_nullifiers.push((nullifier, DUMMY_COMMITMENT_HASH));
|
||||
}
|
||||
(nullifier, DUMMY_COMMITMENT_HASH)
|
||||
};
|
||||
output.new_nullifiers.push(new_nullifier);
|
||||
|
||||
// Update post-state with new nonce
|
||||
let mut post_with_updated_values =
|
||||
state_diff.get(&pre_states[i].account_id).unwrap().clone();
|
||||
post_with_updated_values.nonce = *new_nonce;
|
||||
|
||||
if post_with_updated_values.program_owner == DEFAULT_PROGRAM_ID {
|
||||
// Claim account
|
||||
post_with_updated_values.program_owner = program_id;
|
||||
}
|
||||
let mut post_with_updated_nonce = post_state;
|
||||
let Some(new_nonce) = private_nonces_iter.next() else {
|
||||
panic!("Missing private account nonce");
|
||||
};
|
||||
post_with_updated_nonce.nonce = *new_nonce;
|
||||
|
||||
// Compute commitment
|
||||
let commitment_post = Commitment::new(npk, &post_with_updated_values);
|
||||
let commitment_post = Commitment::new(npk, &post_with_updated_nonce);
|
||||
|
||||
// Encrypt and push post state
|
||||
let encrypted_account = EncryptionScheme::encrypt(
|
||||
&post_with_updated_values,
|
||||
&post_with_updated_nonce,
|
||||
shared_secret,
|
||||
&commitment_post,
|
||||
output_index,
|
||||
);
|
||||
|
||||
new_commitments.push(commitment_post);
|
||||
ciphertexts.push(encrypted_account);
|
||||
output.new_commitments.push(commitment_post);
|
||||
output.ciphertexts.push(encrypted_account);
|
||||
output_index += 1;
|
||||
}
|
||||
_ => panic!("Invalid visibility mask value"),
|
||||
}
|
||||
}
|
||||
|
||||
if private_nonces_iter.next().is_some() {
|
||||
panic!("Too many nonces");
|
||||
}
|
||||
assert!(private_nonces_iter.next().is_none(), "Too many nonces");
|
||||
|
||||
if private_keys_iter.next().is_some() {
|
||||
panic!("Too many private account keys");
|
||||
}
|
||||
assert!(
|
||||
private_keys_iter.next().is_none(),
|
||||
"Too many private account keys"
|
||||
);
|
||||
|
||||
if private_nsks_iter.next().is_some() {
|
||||
panic!("Too many private account authentication keys");
|
||||
}
|
||||
assert!(
|
||||
private_nsks_iter.next().is_none(),
|
||||
"Too many private account nullifier secret keys"
|
||||
);
|
||||
|
||||
if private_membership_proofs_iter.next().is_some() {
|
||||
panic!("Too many private account membership proofs");
|
||||
}
|
||||
assert!(
|
||||
private_membership_proofs_iter.next().is_none(),
|
||||
"Too many private account membership proofs"
|
||||
);
|
||||
|
||||
let output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states,
|
||||
public_post_states,
|
||||
ciphertexts,
|
||||
new_commitments,
|
||||
new_nullifiers,
|
||||
};
|
||||
|
||||
env::commit(&output);
|
||||
output
|
||||
}
|
||||
|
||||
fn compute_nullifier_and_set_digest(
|
||||
membership_proof_opt: Option<&MembershipProof>,
|
||||
pre_account: &Account,
|
||||
npk: &NullifierPublicKey,
|
||||
nsk: &NullifierSecretKey,
|
||||
) -> (Nullifier, CommitmentSetDigest) {
|
||||
membership_proof_opt
|
||||
.as_ref()
|
||||
.map(|membership_proof| {
|
||||
// Compute commitment set digest associated with provided auth path
|
||||
let commitment_pre = Commitment::new(npk, pre_account);
|
||||
let set_digest = compute_digest_for_path(&commitment_pre, membership_proof);
|
||||
|
||||
// Compute update nullifier
|
||||
let nullifier = Nullifier::for_account_update(&commitment_pre, nsk);
|
||||
(nullifier, set_digest)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
assert_eq!(
|
||||
*pre_account,
|
||||
Account::default(),
|
||||
"Found new private account with non default values"
|
||||
);
|
||||
|
||||
// Compute initialization nullifier
|
||||
let nullifier = Nullifier::for_account_initialization(npk);
|
||||
(nullifier, DUMMY_COMMITMENT_HASH)
|
||||
})
|
||||
}
|
||||
|
||||
@ -335,7 +335,7 @@ impl WalletCore {
|
||||
pub async fn send_privacy_preserving_tx(
|
||||
&self,
|
||||
accounts: Vec<PrivacyPreservingAccount>,
|
||||
instruction_data: &InstructionData,
|
||||
instruction_data: InstructionData,
|
||||
program: &ProgramWithDependencies,
|
||||
) -> Result<(SendTxResponse, Vec<SharedSecretKey>), ExecutionFailureKind> {
|
||||
self.send_privacy_preserving_tx_with_pre_check(accounts, instruction_data, program, |_| {
|
||||
@ -347,7 +347,7 @@ impl WalletCore {
|
||||
pub async fn send_privacy_preserving_tx_with_pre_check(
|
||||
&self,
|
||||
accounts: Vec<PrivacyPreservingAccount>,
|
||||
instruction_data: &InstructionData,
|
||||
instruction_data: InstructionData,
|
||||
program: &ProgramWithDependencies,
|
||||
tx_pre_check: impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>,
|
||||
) -> Result<(SendTxResponse, Vec<SharedSecretKey>), ExecutionFailureKind> {
|
||||
@ -363,16 +363,16 @@ impl WalletCore {
|
||||
|
||||
let private_account_keys = acc_manager.private_account_keys();
|
||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
&pre_states,
|
||||
pre_states,
|
||||
instruction_data,
|
||||
acc_manager.visibility_mask(),
|
||||
&produce_random_nonces(private_account_keys.len()),
|
||||
&private_account_keys
|
||||
acc_manager.visibility_mask().to_vec(),
|
||||
produce_random_nonces(private_account_keys.len()),
|
||||
private_account_keys
|
||||
.iter()
|
||||
.map(|keys| (keys.npk.clone(), keys.ssk))
|
||||
.collect::<Vec<_>>(),
|
||||
&acc_manager.private_account_auth(),
|
||||
&acc_manager.private_account_membership_proofs(),
|
||||
acc_manager.private_account_auth(),
|
||||
acc_manager.private_account_membership_proofs(),
|
||||
&program.to_owned(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -19,7 +19,7 @@ impl NativeTokenTransfer<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(from),
|
||||
PrivacyPreservingAccount::Public(to),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&program.into(),
|
||||
tx_pre_check,
|
||||
)
|
||||
|
||||
@ -17,7 +17,7 @@ impl NativeTokenTransfer<'_> {
|
||||
self.0
|
||||
.send_privacy_preserving_tx_with_pre_check(
|
||||
vec![PrivacyPreservingAccount::PrivateOwned(from)],
|
||||
&Program::serialize_instruction(instruction).unwrap(),
|
||||
Program::serialize_instruction(instruction).unwrap(),
|
||||
&Program::authenticated_transfer_program().into(),
|
||||
|_| Ok(()),
|
||||
)
|
||||
@ -47,7 +47,7 @@ impl NativeTokenTransfer<'_> {
|
||||
ipk: to_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&program.into(),
|
||||
tx_pre_check,
|
||||
)
|
||||
@ -74,7 +74,7 @@ impl NativeTokenTransfer<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(from),
|
||||
PrivacyPreservingAccount::PrivateOwned(to),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&program.into(),
|
||||
tx_pre_check,
|
||||
)
|
||||
|
||||
@ -20,7 +20,7 @@ impl NativeTokenTransfer<'_> {
|
||||
PrivacyPreservingAccount::Public(from),
|
||||
PrivacyPreservingAccount::PrivateOwned(to),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&program.into(),
|
||||
tx_pre_check,
|
||||
)
|
||||
@ -52,7 +52,7 @@ impl NativeTokenTransfer<'_> {
|
||||
ipk: to_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&program.into(),
|
||||
tx_pre_check,
|
||||
)
|
||||
|
||||
@ -37,7 +37,7 @@ impl Pinata<'_> {
|
||||
PrivacyPreservingAccount::Public(pinata_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(winner_account_id),
|
||||
],
|
||||
&nssa::program::Program::serialize_instruction(solution).unwrap(),
|
||||
nssa::program::Program::serialize_instruction(solution).unwrap(),
|
||||
&nssa::program::Program::pinata().into(),
|
||||
)
|
||||
.await
|
||||
|
||||
@ -52,7 +52,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(supply_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -82,7 +82,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::Public(supply_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -112,7 +112,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(supply_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -180,7 +180,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -212,7 +212,7 @@ impl Token<'_> {
|
||||
ipk: recipient_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -240,7 +240,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
|
||||
PrivacyPreservingAccount::Public(recipient_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -269,7 +269,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(sender_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -302,7 +302,7 @@ impl Token<'_> {
|
||||
ipk: recipient_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -365,7 +365,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -393,7 +393,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::Public(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -422,7 +422,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -491,7 +491,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -523,7 +523,7 @@ impl Token<'_> {
|
||||
ipk: holder_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -551,7 +551,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::Public(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -580,7 +580,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
@ -613,7 +613,7 @@ impl Token<'_> {
|
||||
ipk: holder_ipk,
|
||||
},
|
||||
],
|
||||
&instruction_data,
|
||||
instruction_data,
|
||||
&Program::token().into(),
|
||||
)
|
||||
.await
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user