add tansfer multiple program

This commit is contained in:
Sergio Chouhy 2025-07-17 11:07:18 -03:00
parent f6a8a11f98
commit 8234c0cb68
9 changed files with 105 additions and 16 deletions

View File

@ -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"] }

View File

@ -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 <Npk> 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::<TransferProgram>(
&[sender, receiver],
&balance_to_move,
let receipt = nssa::execute_and_prove_privacy_execution::<TransferMultipleProgram>(
&[sender, receiver_1, receiver_2],
&vec![30, 40],
&visibilities,
root,
)

View File

@ -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::<TransferProgram>(&[sender, receiver], &balance_to_move).unwrap();
nssa::execute::<TransferMultipleProgram>(&[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],
);
}

View File

@ -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<u128>;
}

View File

@ -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"]

View File

@ -0,0 +1,3 @@
fn main() {
risc0_build::embed_methods();
}

View File

@ -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" }

View File

@ -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<Account> = env::read();
let target_balances: Vec<u128> = 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<Account> = vec![sender]
.into_iter()
.chain(receivers)
.chain(vec![sender_post])
.chain(receivers_post)
.collect();
env::commit(&inputs_outputs);
}

View File

@ -0,0 +1 @@
include!(concat!(env!("OUT_DIR"), "/methods.rs"));