mirror of
https://github.com/logos-blockchain/lssa-zkvm-testing.git
synced 2026-01-08 08:13:10 +00:00
generalize code to prove any privacy execution
This commit is contained in:
parent
b6bec23ac2
commit
b622cb8040
@ -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<P: Program>(
|
||||
inputs: &[Account],
|
||||
instruction_data: &P::InstructionData,
|
||||
visibilities: &[InputVisibiility],
|
||||
commitment_tree_root: [u32; 8],
|
||||
) -> Result<ProveInfo, ()> {
|
||||
// Prove inner program and get post state of the accounts
|
||||
let num_inputs = inputs.len();
|
||||
let (inner_receipt, inputs_outputs) = execute_and_prove::<P>(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::<TransferProgram>(
|
||||
&[sender, receiver],
|
||||
&balance_to_move,
|
||||
&visibilities,
|
||||
root,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let receipt = prove_info.receipt;
|
||||
|
||||
|
||||
@ -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<Account>), ()> {
|
||||
// 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<Account> = receipt.journal.decode().map_err(|_| ())?;
|
||||
|
||||
Ok((receipt, inputs_outputs))
|
||||
}
|
||||
|
||||
fn execute(
|
||||
input_accounts: &[Account],
|
||||
instruction_data: &Self::InstructionData,
|
||||
) -> Result<Vec<Account>, ()> {
|
||||
// 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<Account> = session_info.journal.decode().map_err(|_| ())?;
|
||||
|
||||
Ok(inputs_outputs)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_inputs<P: Program>(
|
||||
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<P: Program>(
|
||||
input_accounts: &[Account],
|
||||
instruction_data: &P::InstructionData,
|
||||
) -> Result<(Receipt, Vec<Account>), ()> {
|
||||
// Write inputs to the program
|
||||
let mut env_builder = ExecutorEnv::builder();
|
||||
write_inputs::<P>(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<Account> = receipt.journal.decode().map_err(|_| ())?;
|
||||
|
||||
Ok((receipt, inputs_outputs))
|
||||
}
|
||||
|
||||
pub(crate) fn execute<P: Program>(
|
||||
input_accounts: &[Account],
|
||||
instruction_data: &P::InstructionData,
|
||||
) -> Result<Vec<Account>, ()> {
|
||||
// Write inputs to the program
|
||||
let mut env_builder = ExecutorEnv::builder();
|
||||
write_inputs::<P>(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<Account> = session_info.journal.decode().map_err(|_| ())?;
|
||||
|
||||
Ok(inputs_outputs)
|
||||
}
|
||||
|
||||
@ -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::<TransferProgram>(&[sender, receiver], &balance_to_move).unwrap();
|
||||
|
||||
println!(
|
||||
"sender_before: {:?}, sender_after: {:?}",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user