diff --git a/risc0-selective-privacy-poc/src/private_execution.rs b/risc0-selective-privacy-poc/src/private_execution.rs index f536727..1576cef 100644 --- a/risc0-selective-privacy-poc/src/private_execution.rs +++ b/risc0-selective-privacy-poc/src/private_execution.rs @@ -1,6 +1,6 @@ use outer_methods::{OUTER_ELF, OUTER_ID}; use rand::{rngs::OsRng, Rng}; -use risc0_zkvm::{default_prover, ExecutorEnv, Receipt}; +use risc0_zkvm::{default_prover, ExecutorEnv, ProveInfo, Receipt}; use sparse_merkle_tree::SparseMerkleTree; use toy_example_core::{ account::Account, @@ -10,7 +10,7 @@ use toy_example_core::{ }; use transfer_methods::{TRANSFER_ELF, TRANSFER_ID}; -use crate::program::Program; +use crate::program::{execute_and_prove, Program}; use crate::TransferProgram; pub fn new_random_nonce() -> Nonce { @@ -23,6 +23,36 @@ fn mint_fresh_account(address: Address) -> Account { Account::new(address, nonce) } +fn prove_privacy_execution( + inputs: &[Account], + instruction_data: &P::InstructionData, + visibilities: &[InputVisibiility], + commitment_tree_root: [u32; 8], +) -> Result { + // Prove inner program and get post state of the accounts + let num_inputs = inputs.len(); + let (inner_receipt, inputs_outputs) = execute_and_prove::

(inputs, instruction_data)?; + + // Sample fresh random nonces for the outputs of this execution + let output_nonces: Vec<_> = (0..num_inputs).map(|_| new_random_nonce()).collect(); + + // Prove outer program. + // This computes the nullifiers for the input accounts and commitments for the output accounts. + let mut env_builder = ExecutorEnv::builder(); + env_builder.add_assumption(inner_receipt); + env_builder.write(&(num_inputs as u32)).unwrap(); + env_builder.write(&inputs_outputs).unwrap(); + env_builder.write(&visibilities).unwrap(); + env_builder.write(&output_nonces).unwrap(); + env_builder.write(&commitment_tree_root).unwrap(); + env_builder.write(&TRANSFER_ID).unwrap(); + let env = env_builder.build().unwrap(); + + let prover = default_prover(); + let prove_info = prover.prove(env, OUTER_ELF).unwrap(); + Ok(prove_info) +} + /// A private execution of the transfer function. /// This actually "burns" a sender private account and "mints" two new private accounts: /// one for the recipient with the transferred balance, and another owned by the sender with the remaining balance. @@ -52,35 +82,17 @@ fn run_private_execution_of_transfer_program() { let receiver_address = [99; 8]; let receiver = mint_fresh_account(receiver_address); - // Prove inner program and get post state of the accounts - let (inner_receipt, inputs_outputs) = - TransferProgram::execute_and_prove(&[sender, receiver], &balance_to_move).unwrap(); - let visibilities = vec![ InputVisibiility::Private(Some((sender_private_key, auth_path))), InputVisibiility::Private(None), ]; - - let num_inputs: u32 = inputs_outputs.len() as u32 / 2; - - // Sample fresh random nonces for the outputs of this execution - let output_nonces: Vec<_> = (0..num_inputs).map(|_| new_random_nonce()).collect(); - println!("output nonces {output_nonces:?}"); - - // Prove outer program. - // This computes the nullifier for the input account and commitments for the accounts post states. - let mut env_builder = ExecutorEnv::builder(); - env_builder.add_assumption(inner_receipt); - env_builder.write(&num_inputs).unwrap(); - env_builder.write(&inputs_outputs).unwrap(); - env_builder.write(&visibilities).unwrap(); - env_builder.write(&output_nonces).unwrap(); - env_builder.write(&root).unwrap(); - env_builder.write(&TRANSFER_ID).unwrap(); - let env = env_builder.build().unwrap(); - - let prover = default_prover(); - let prove_info = prover.prove(env, OUTER_ELF).unwrap(); + let prove_info = prove_privacy_execution::( + &[sender, receiver], + &balance_to_move, + &visibilities, + root, + ) + .unwrap(); let receipt = prove_info.receipt; diff --git a/risc0-selective-privacy-poc/src/program.rs b/risc0-selective-privacy-poc/src/program.rs index 45988ac..bf31cf1 100644 --- a/risc0-selective-privacy-poc/src/program.rs +++ b/risc0-selective-privacy-poc/src/program.rs @@ -6,55 +6,55 @@ pub(crate) trait Program { const PROGRAM_ID: [u32; 8]; const PROGRAM_ELF: &[u8]; type InstructionData: Serialize + for<'de> Deserialize<'de>; - - fn write_inputs( - input_accounts: &[Account], - instruction_data: &Self::InstructionData, - env_builder: &mut ExecutorEnvBuilder, - ) -> Result<(), ()> { - for account in input_accounts { - env_builder.write(&account).map_err(|_| ())?; - } - env_builder.write(&instruction_data).map_err(|_| ())?; - Ok(()) - } - - fn execute_and_prove( - input_accounts: &[Account], - instruction_data: &Self::InstructionData, - ) -> Result<(Receipt, Vec), ()> { - // Write inputs to the program - let mut env_builder = ExecutorEnv::builder(); - Self::write_inputs(input_accounts, instruction_data, &mut env_builder)?; - let env = env_builder.build().unwrap(); - - // Prove the program - let prover = default_prover(); - let prove_info = prover.prove(env, Self::PROGRAM_ELF).map_err(|_| ())?; - let receipt = prove_info.receipt; - - // Get proof and (inputs and) outputs - let inputs_outputs: Vec = receipt.journal.decode().map_err(|_| ())?; - - Ok((receipt, inputs_outputs)) - } - - fn execute( - input_accounts: &[Account], - instruction_data: &Self::InstructionData, - ) -> Result, ()> { - // Write inputs to the program - let mut env_builder = ExecutorEnv::builder(); - Self::write_inputs(input_accounts, instruction_data, &mut env_builder)?; - let env = env_builder.build().unwrap(); - - // Execute the program (without proving) - let executor = default_executor(); - let session_info = executor.execute(env, Self::PROGRAM_ELF).map_err(|_| ())?; - - // Get proof and (inputs and) outputs - let inputs_outputs: Vec = session_info.journal.decode().map_err(|_| ())?; - - Ok(inputs_outputs) - } +} + +pub(crate) fn write_inputs( + input_accounts: &[Account], + instruction_data: &P::InstructionData, + env_builder: &mut ExecutorEnvBuilder, +) -> Result<(), ()> { + for account in input_accounts { + env_builder.write(&account).map_err(|_| ())?; + } + env_builder.write(&instruction_data).map_err(|_| ())?; + Ok(()) +} + +pub(crate) fn execute_and_prove( + input_accounts: &[Account], + instruction_data: &P::InstructionData, +) -> Result<(Receipt, Vec), ()> { + // Write inputs to the program + let mut env_builder = ExecutorEnv::builder(); + write_inputs::

(input_accounts, instruction_data, &mut env_builder)?; + let env = env_builder.build().unwrap(); + + // Prove the program + let prover = default_prover(); + let prove_info = prover.prove(env, P::PROGRAM_ELF).map_err(|_| ())?; + let receipt = prove_info.receipt; + + // Get proof and (inputs and) outputs + let inputs_outputs: Vec = receipt.journal.decode().map_err(|_| ())?; + + Ok((receipt, inputs_outputs)) +} + +pub(crate) fn execute( + input_accounts: &[Account], + instruction_data: &P::InstructionData, +) -> Result, ()> { + // Write inputs to the program + let mut env_builder = ExecutorEnv::builder(); + write_inputs::

(input_accounts, instruction_data, &mut env_builder)?; + let env = env_builder.build().unwrap(); + + // Execute the program (without proving) + let executor = default_executor(); + let session_info = executor.execute(env, P::PROGRAM_ELF).map_err(|_| ())?; + + // Get proof and (inputs and) outputs + let inputs_outputs: Vec = session_info.journal.decode().map_err(|_| ())?; + + Ok(inputs_outputs) } diff --git a/risc0-selective-privacy-poc/src/public_execution.rs b/risc0-selective-privacy-poc/src/public_execution.rs index 3917ca8..44395a9 100644 --- a/risc0-selective-privacy-poc/src/public_execution.rs +++ b/risc0-selective-privacy-poc/src/public_execution.rs @@ -2,7 +2,10 @@ use risc0_zkvm::{default_executor, ExecutorEnv}; use toy_example_core::account::Account; use transfer_methods::TRANSFER_ELF; -use crate::{program::Program, TransferProgram}; +use crate::{ + program::{execute, Program}, + TransferProgram, +}; /// A public execution. /// This would be executed by the runtime after checking that @@ -24,7 +27,7 @@ pub fn run_public_execution_of_transfer_program() { let balance_to_move: u128 = 3; - let inputs_outputs = TransferProgram::execute(&[sender, receiver], &balance_to_move).unwrap(); + let inputs_outputs = execute::(&[sender, receiver], &balance_to_move).unwrap(); println!( "sender_before: {:?}, sender_after: {:?}",