This commit is contained in:
Sergio Chouhy 2025-07-16 17:28:45 -03:00
parent d4a306d67a
commit 3d582d491f
5 changed files with 101 additions and 103 deletions

View File

@ -11,7 +11,7 @@ use toy_example_core::{
types::{Address, AuthenticationPath, Commitment, Nonce, Nullifier},
};
use transfer_methods::{TRANSFER_ELF, TRANSFER_ID};
use tuki::program::{prove_privacy_execution, Program};
use tuki::{prove_privacy_execution, Program};
fn mint_fresh_account(address: Address) -> Account {
let nonce = [0; 8];

View File

@ -1,5 +1,5 @@
use transfer_methods::{TRANSFER_ELF, TRANSFER_ID};
use tuki::program::Program;
use tuki::Program;
pub struct TransferProgram;

View File

@ -4,7 +4,7 @@ use risc0_zkvm::{default_executor, ExecutorEnv};
use toy_example_core::account::Account;
use transfer_methods::TRANSFER_ELF;
use tuki::program::{execute, Program};
use tuki::{execute, Program};
use crate::programs::TransferProgram;

View File

@ -1,2 +1,99 @@
pub mod program;
use outer_methods::OUTER_ELF;
use rand::{rngs::OsRng, Rng};
use risc0_zkvm::{
default_executor, default_prover, ExecutorEnv, ExecutorEnvBuilder, ProveInfo, Receipt,
};
use serde::{Deserialize, Serialize};
use toy_example_core::{account::Account, input::InputVisibiility, types::Nonce};
pub fn new_random_nonce() -> Nonce {
let mut rng = OsRng;
std::array::from_fn(|_| rng.gen())
}
pub trait Program {
const PROGRAM_ID: [u32; 8];
const PROGRAM_ELF: &[u8];
type InstructionData: Serialize + for<'de> Deserialize<'de>;
}
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 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)
}
pub 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(&P::PROGRAM_ID).unwrap();
let env = env_builder.build().unwrap();
let prover = default_prover();
let prove_info = prover.prove(env, OUTER_ELF).unwrap();
Ok(prove_info)
}

View File

@ -1,99 +0,0 @@
use outer_methods::OUTER_ELF;
use rand::{rngs::OsRng, Rng};
use risc0_zkvm::{
default_executor, default_prover, ExecutorEnv, ExecutorEnvBuilder, ProveInfo, Receipt,
};
use serde::{Deserialize, Serialize};
use toy_example_core::{account::Account, input::InputVisibiility, types::Nonce};
pub fn new_random_nonce() -> Nonce {
let mut rng = OsRng;
std::array::from_fn(|_| rng.gen())
}
pub trait Program {
const PROGRAM_ID: [u32; 8];
const PROGRAM_ELF: &[u8];
type InstructionData: Serialize + for<'de> Deserialize<'de>;
}
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 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)
}
pub 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(&P::PROGRAM_ID).unwrap();
let env = env_builder.build().unwrap();
let prover = default_prover();
let prove_info = prover.prove(env, OUTER_ELF).unwrap();
Ok(prove_info)
}