diff --git a/risc0-selective-privacy-poc/Cargo.toml b/risc0-selective-privacy-poc/Cargo.toml index e159416..0228bc8 100644 --- a/risc0-selective-privacy-poc/Cargo.toml +++ b/risc0-selective-privacy-poc/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" risc0-zkvm = "2.2" core = { path = "core" } transfer-methods = { path = "transfer_methods" } +transfer-multiple-methods = { path = "transfer_multiple_methods" } outer-methods = { path = "outer_methods" } serde = "1.0" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/risc0-selective-privacy-poc/examples/private_execution.rs b/risc0-selective-privacy-poc/examples/private_execution.rs index 501bcff..36f25c4 100644 --- a/risc0-selective-privacy-poc/examples/private_execution.rs +++ b/risc0-selective-privacy-poc/examples/private_execution.rs @@ -1,12 +1,12 @@ -use nssa::program::TransferProgram; -use outer_methods::OUTER_ID; -use sparse_merkle_tree::SparseMerkleTree; use core::{ account::Account, bytes_to_words, input::InputVisibiility, types::{Address, AuthenticationPath, Commitment, Nullifier}, }; +use nssa::program::TransferMultipleProgram; +use outer_methods::OUTER_ID; +use sparse_merkle_tree::SparseMerkleTree; fn mint_fresh_account(address: Address) -> Account { let nonce = [0; 8]; @@ -39,17 +39,21 @@ fn main() { let balance_to_move: u128 = 3; // This is the new private account (UTXO) being minted by this private execution. (The `receiver_address` would be in UTXO's terminology) - let receiver_address = [99; 8]; - let receiver = mint_fresh_account(receiver_address); + let receiver_address_1 = [99; 8]; + let receiver_1 = mint_fresh_account(receiver_address_1); + + let receiver_address_2 = [100; 8]; + let receiver_2 = mint_fresh_account(receiver_address_2); let visibilities = vec![ InputVisibiility::Private(Some((sender_private_key, auth_path))), InputVisibiility::Private(None), + InputVisibiility::Private(None), ]; - let receipt = nssa::execute_and_prove_privacy_execution::( - &[sender, receiver], - &balance_to_move, + let receipt = nssa::execute_and_prove_privacy_execution::( + &[sender, receiver_1, receiver_2], + &vec![30, 40], &visibilities, root, ) diff --git a/risc0-selective-privacy-poc/examples/public_execution.rs b/risc0-selective-privacy-poc/examples/public_execution.rs index 1095886..03d3256 100644 --- a/risc0-selective-privacy-poc/examples/public_execution.rs +++ b/risc0-selective-privacy-poc/examples/public_execution.rs @@ -1,10 +1,9 @@ use risc0_zkvm::{default_executor, ExecutorEnv}; use core::account::Account; -use transfer_methods::TRANSFER_ELF; use nssa; -use nssa::program::TransferProgram; +use nssa::program::TransferMultipleProgram; /// A public execution. /// This would be executed by the runtime after checking that @@ -18,23 +17,33 @@ pub fn main() { }; // Account fetched from the chain state with 900 in its balance. - let receiver = { + let receiver_1 = { let mut account = Account::new([6; 8], [99; 8]); account.balance = 900; account }; - let balance_to_move: u128 = 3; + let receiver_2 = { + let mut account = Account::new([6; 8], [99; 8]); + account.balance = 500; + account + }; + + let balance_to_move = vec![10, 20]; let inputs_outputs = - nssa::execute::(&[sender, receiver], &balance_to_move).unwrap(); + nssa::execute::(&[sender, receiver_1, receiver_2], &balance_to_move).unwrap(); println!( "sender_before: {:?}, sender_after: {:?}", - inputs_outputs[0], inputs_outputs[2] + inputs_outputs[0], inputs_outputs[3] ); println!( - "receiver_before: {:?}, receiver_after: {:?}", - inputs_outputs[1], inputs_outputs[3], + "receiver_1_before: {:?}, receiver_1_after: {:?}", + inputs_outputs[1], inputs_outputs[4], + ); + println!( + "receiver_2_before: {:?}, receiver_2_after: {:?}", + inputs_outputs[2], inputs_outputs[5], ); } diff --git a/risc0-selective-privacy-poc/src/program/mod.rs b/risc0-selective-privacy-poc/src/program/mod.rs index a9af5fc..aafe0c7 100644 --- a/risc0-selective-privacy-poc/src/program/mod.rs +++ b/risc0-selective-privacy-poc/src/program/mod.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use transfer_methods::{TRANSFER_ELF, TRANSFER_ID}; +use transfer_multiple_methods::{TRANSFER_MULTIPLE_ELF, TRANSFER_MULTIPLE_ID}; pub trait Program { const PROGRAM_ID: [u32; 8]; @@ -14,3 +15,11 @@ impl Program for TransferProgram { // Amount to transfer type InstructionData = u128; } + +pub struct TransferMultipleProgram; +impl Program for TransferMultipleProgram { + const PROGRAM_ID: [u32; 8] = TRANSFER_MULTIPLE_ID; + const PROGRAM_ELF: &[u8] = TRANSFER_MULTIPLE_ELF; + // Amounts to transfer + type InstructionData = Vec; +} diff --git a/risc0-selective-privacy-poc/transfer_multiple_methods/Cargo.toml b/risc0-selective-privacy-poc/transfer_multiple_methods/Cargo.toml new file mode 100644 index 0000000..6510d09 --- /dev/null +++ b/risc0-selective-privacy-poc/transfer_multiple_methods/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "transfer-multiple-methods" +version = "0.1.0" +edition = "2021" + +[build-dependencies] +risc0-build = { version = "2.2" } + +[package.metadata.risc0] +methods = ["guest"] diff --git a/risc0-selective-privacy-poc/transfer_multiple_methods/build.rs b/risc0-selective-privacy-poc/transfer_multiple_methods/build.rs new file mode 100644 index 0000000..08a8a4e --- /dev/null +++ b/risc0-selective-privacy-poc/transfer_multiple_methods/build.rs @@ -0,0 +1,3 @@ +fn main() { + risc0_build::embed_methods(); +} diff --git a/risc0-selective-privacy-poc/transfer_multiple_methods/guest/Cargo.toml b/risc0-selective-privacy-poc/transfer_multiple_methods/guest/Cargo.toml new file mode 100644 index 0000000..2a7395e --- /dev/null +++ b/risc0-selective-privacy-poc/transfer_multiple_methods/guest/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "transfer-multiple" +version = "0.1.0" +edition = "2021" + +[workspace] + +[dependencies] +risc0-zkvm = { version = "2.2.0", default-features = false, features = ['std'] } +core = { path = "../../core" } diff --git a/risc0-selective-privacy-poc/transfer_multiple_methods/guest/src/bin/transfer_multiple.rs b/risc0-selective-privacy-poc/transfer_multiple_methods/guest/src/bin/transfer_multiple.rs new file mode 100644 index 0000000..03ef52b --- /dev/null +++ b/risc0-selective-privacy-poc/transfer_multiple_methods/guest/src/bin/transfer_multiple.rs @@ -0,0 +1,42 @@ +use core::account::Account; +use risc0_zkvm::{ + guest::env, + serde::to_vec, + sha::{Impl, Sha256}, +}; + +/// A transfer of balance program with multiple recipients. +/// To be used both in public and private contexts. +fn main() { + let mut input_accounts: Vec = env::read(); + let target_balances: Vec = env::read(); + + assert!(input_accounts.len() > 1); + assert_eq!(target_balances.len() + 1, input_accounts.len()); + + let receivers = input_accounts.split_off(1); + let sender = input_accounts.pop().unwrap(); + let total_balance_to_move = target_balances.iter().sum(); + + // Check sender has enough balance + assert!(sender.balance >= total_balance_to_move); + + // Create accounts post states, with updated balances + let mut sender_post = sender.clone(); + let mut receivers_post = receivers.clone(); + + sender_post.balance -= total_balance_to_move; + for (receiver, balance_for_receiver) in receivers_post.iter_mut().zip(target_balances) { + receiver.balance += balance_for_receiver; + } + + // Flatten pre and post states for output + let inputs_outputs: Vec = vec![sender] + .into_iter() + .chain(receivers) + .chain(vec![sender_post]) + .chain(receivers_post) + .collect(); + + env::commit(&inputs_outputs); +} diff --git a/risc0-selective-privacy-poc/transfer_multiple_methods/src/lib.rs b/risc0-selective-privacy-poc/transfer_multiple_methods/src/lib.rs new file mode 100644 index 0000000..1bdb308 --- /dev/null +++ b/risc0-selective-privacy-poc/transfer_multiple_methods/src/lib.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/methods.rs"));