add program deployment examples

This commit is contained in:
Sergio Chouhy
2025-12-11 20:59:37 -03:00
parent abb1fc5e45
commit 8c92a58bbc
22 changed files with 1349 additions and 15 deletions
@@ -0,0 +1,67 @@
use nssa::{
AccountId, PublicTransaction,
program::Program,
public_transaction::{Message, WitnessSet},
};
use wallet::{WalletCore, helperfunctions::fetch_config};
// Before running this example, compile the `hello_world.rs` guest program with:
//
// cargo risczero build --manifest-path examples/program_deployment/methods/guest/Cargo.toml
//
// Note: you must run the above command from the root of the `lssa` repository.
// Note: The compiled binary file is stored in
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world.bin
//
//
// Usage:
// cargo run --bin run_hello_world /path/to/guest/binary <account_id>
//
// Example:
// cargo run --bin run_hello_world \
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world.bin \
// Ds8q5PjLcKwwV97Zi7duhRVF9uwA2PuYMoLL7FwCzsXE
#[tokio::main]
async fn main() {
// Load wallet config and storage
let wallet_config = fetch_config().await.unwrap();
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config)
.await
.unwrap();
// Parse arguments
// First argument is the path to the program binary
let program_path = std::env::args_os().nth(1).unwrap().into_string().unwrap();
// Second argument is the account_id
let account_id: AccountId = std::env::args_os()
.nth(2)
.unwrap()
.into_string()
.unwrap()
.parse()
.unwrap();
// Load the program
let bytecode: Vec<u8> = std::fs::read(program_path).unwrap();
let program = Program::new(bytecode).unwrap();
// Define the desired greeting in ASCII
let greeting: Vec<u8> = vec![72, 111, 108, 97, 32, 109, 117, 110, 100, 111, 33];
// Construct the public transaction
// No nonces nor signing keys are needed for this example. Check out the
// `run_hello_world_with_authorization` on how to use them.
let nonces = vec![];
let signing_keys = [];
let message = Message::try_new(program.id(), vec![account_id], nonces, greeting).unwrap();
let witness_set = WitnessSet::for_message(&message, &signing_keys);
let tx = PublicTransaction::new(message, witness_set);
// Submit the transaction
let _response = wallet_core
.sequencer_client
.send_tx_public(tx)
.await
.unwrap();
}
@@ -0,0 +1,61 @@
use nssa::{AccountId, program::Program};
use wallet::{PrivacyPreservingAccount, WalletCore, helperfunctions::fetch_config};
// Before running this example, compile the `hello_world.rs` guest program with:
//
// cargo risczero build --manifest-path examples/program_deployment/methods/guest/Cargo.toml
//
// Note: you must run the above command from the root of the `lssa` repository.
// Note: The compiled binary file is stored in
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world.bin
//
//
// Usage:
// cargo run --bin run_hello_world_private /path/to/guest/binary <account_id>
//
// Note: the provided account_id needs to be of a private self owned account
//
// Example:
// cargo run --bin run_hello_world_private \
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world.bin \
// Ds8q5PjLcKwwV97Zi7duhRVF9uwA2PuYMoLL7FwCzsXE
#[tokio::main]
async fn main() {
// Load wallet config and storage
let wallet_config = fetch_config().await.unwrap();
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config)
.await
.unwrap();
// Parse arguments
// First argument is the path to the program binary
let program_path = std::env::args_os().nth(1).unwrap().into_string().unwrap();
// Second argument is the account_id
let account_id: AccountId = std::env::args_os()
.nth(2)
.unwrap()
.into_string()
.unwrap()
.parse()
.unwrap();
// Load the program
let bytecode: Vec<u8> = std::fs::read(program_path).unwrap();
let program = Program::new(bytecode).unwrap();
// Define the desired greeting in ASCII
let greeting: Vec<u8> = vec![72, 111, 108, 97, 32, 109, 117, 110, 100, 111, 33];
let accounts = vec![PrivacyPreservingAccount::PrivateOwned(account_id)];
// Construct and submit the privacy-preserving transaction
wallet_core
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(greeting).unwrap(),
&program,
)
.await
.unwrap();
}
@@ -0,0 +1,63 @@
use nssa::{
AccountId, PublicTransaction,
program::Program,
public_transaction::{Message, WitnessSet},
};
use wallet::{WalletCore, helperfunctions::fetch_config};
// Before running this example, compile the `simple_tail_call.rs` guest program with:
//
// cargo risczero build --manifest-path examples/program_deployment/methods/guest/Cargo.toml
//
// Note: you must run the above command from the root of the `lssa` repository.
// Note: The compiled binary file is stored in
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/simple_tail_call.bin
//
//
// Usage:
// cargo run --bin run_hello_world_through_tail_call /path/to/guest/binary <account_id>
//
// Example:
// cargo run --bin run_hello_world_through_tail_call \
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/simple_tail_call.bin \
// Ds8q5PjLcKwwV97Zi7duhRVF9uwA2PuYMoLL7FwCzsXE
#[tokio::main]
async fn main() {
// Load wallet config and storage
let wallet_config = fetch_config().await.unwrap();
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config)
.await
.unwrap();
// Parse arguments
// First argument is the path to the program binary
let program_path = std::env::args_os().nth(1).unwrap().into_string().unwrap();
// Second argument is the account_id
let account_id: AccountId = std::env::args_os()
.nth(2)
.unwrap()
.into_string()
.unwrap()
.parse()
.unwrap();
// Load the program
let bytecode: Vec<u8> = std::fs::read(program_path).unwrap();
let program = Program::new(bytecode).unwrap();
let instruction_data = ();
let nonces = vec![];
let signing_keys = [];
let message =
Message::try_new(program.id(), vec![account_id], nonces, instruction_data).unwrap();
let witness_set = WitnessSet::for_message(&message, &signing_keys);
let tx = PublicTransaction::new(message, witness_set);
// Submit the transaction
let _response = wallet_core
.sequencer_client
.send_tx_public(tx)
.await
.unwrap();
}
@@ -0,0 +1,80 @@
use nssa::{
AccountId, PublicTransaction,
program::Program,
public_transaction::{Message, WitnessSet},
};
use wallet::{WalletCore, helperfunctions::fetch_config};
// Before running this example, compile the `hello_world_with_authorization.rs` guest program with:
//
// cargo risczero build --manifest-path examples/program_deployment/methods/guest/Cargo.toml
//
// Note: you must run the above command from the root of the `lssa` repository.
// Note: The compiled binary file is stored in
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world_with_authorization.bin
//
//
// Usage:
// ./run_hello_world_with_authorization /path/to/guest/binary <account_id>
//
// Note: the provided account_id needs to be of a public self owned account
//
// Example:
// cargo run --bin run_hello_world_with_authorization \
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world_with_authorization.bin \
// Ds8q5PjLcKwwV97Zi7duhRVF9uwA2PuYMoLL7FwCzsXE
#[tokio::main]
async fn main() {
// Load wallet config and storage
let wallet_config = fetch_config().await.unwrap();
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config)
.await
.unwrap();
// Parse arguments
// First argument is the path to the program binary
let program_path = std::env::args_os().nth(1).unwrap().into_string().unwrap();
// Second argument is the account_id
let account_id: AccountId = std::env::args_os()
.nth(2)
.unwrap()
.into_string()
.unwrap()
.parse()
.unwrap();
// Load the program
let bytecode: Vec<u8> = std::fs::read(program_path).unwrap();
let program = Program::new(bytecode).unwrap();
// Load signing keys to provide authorization
let signing_key = wallet_core
.storage
.user_data
.get_pub_account_signing_key(&account_id)
.expect("Input account should be a self owned public account");
// Define the desired greeting in ASCII
let greeting: Vec<u8> = vec![72, 111, 108, 97, 32, 109, 117, 110, 100, 111, 33];
// Construct the public transaction
// Query the current nonce from the node
let nonces = wallet_core
.get_accounts_nonces(vec![account_id])
.await
.expect("Node should be reachable to query account data");
let signing_keys = [signing_key];
let message = Message::try_new(program.id(), vec![account_id], nonces, greeting).unwrap();
// Pass the signing key to sign the message. This will be used by the node
// to flag the pre_state as `is_authorized` when executing the program
let witness_set = WitnessSet::for_message(&message, &signing_keys);
let tx = PublicTransaction::new(message, witness_set);
// Submit the transaction
let _response = wallet_core
.sequencer_client
.send_tx_public(tx)
.await
.unwrap();
}
@@ -0,0 +1,155 @@
use clap::{Parser, Subcommand};
use nssa::{PublicTransaction, program::Program, public_transaction};
use wallet::{PrivacyPreservingAccount, WalletCore, helperfunctions::fetch_config};
// Before running this example, compile the `hello_world_with_move_function.rs` guest program with:
//
// cargo risczero build --manifest-path examples/program_deployment/methods/guest/Cargo.toml
//
// Note: you must run the above command from the root of the `lssa` repository.
// Note: The compiled binary file is stored in
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world_with_move_function.bin
//
//
// Usage:
// cargo run --bin run_hello_world_with_move_function /path/to/guest/binary <function> <params>
//
// Example:
// cargo run --bin run_hello_world_with_move_function \
// methods/guest/target/riscv32im-risc0-zkvm-elf/docker/hello_world_with_move_function.bin \
// write-public Ds8q5PjLcKwwV97Zi7duhRVF9uwA2PuYMoLL7FwCzsXE Hola
type Instruction = (u8, Vec<u8>);
const WRITE_FUNCTION_ID: u8 = 0;
const MOVE_DATA_FUNCTION_ID: u8 = 1;
#[derive(Parser, Debug)]
struct Cli {
/// Path to program binary
program_path: String,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand, Debug)]
enum Command {
/// Write instruction into one account
WritePublic {
account_id: String,
greeting: String,
},
WritePrivate {
account_id: String,
greeting: String,
},
/// Move data between two accounts
MoveDataPublicToPublic {
from: String,
to: String,
},
MoveDataPublicToPrivate {
from: String,
to: String,
},
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
// Load the program
let bytecode: Vec<u8> = std::fs::read(cli.program_path).unwrap();
let program = Program::new(bytecode).unwrap();
// Load wallet config and storage
let wallet_config = fetch_config().await.unwrap();
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config)
.await
.unwrap();
match cli.command {
Command::WritePublic {
account_id,
greeting,
} => {
let instruction: Instruction = (WRITE_FUNCTION_ID, greeting.into_bytes());
let account_id = account_id.parse().unwrap();
let nonces = vec![];
let message = public_transaction::Message::try_new(
program.id(),
vec![account_id],
nonces,
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(&message, &[]);
let tx = PublicTransaction::new(message, witness_set);
// Submit the transaction
let _response = wallet_core
.sequencer_client
.send_tx_public(tx)
.await
.unwrap();
}
Command::WritePrivate {
account_id,
greeting,
} => {
let instruction: Instruction = (WRITE_FUNCTION_ID, greeting.into_bytes());
let account_id = account_id.parse().unwrap();
let accounts = vec![PrivacyPreservingAccount::PrivateOwned(account_id)];
wallet_core
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(instruction).unwrap(),
&program,
)
.await
.unwrap();
}
Command::MoveDataPublicToPublic { from, to } => {
let instruction: Instruction = (MOVE_DATA_FUNCTION_ID, vec![]);
let from = from.parse().unwrap();
let to = to.parse().unwrap();
let nonces = vec![];
let message = public_transaction::Message::try_new(
program.id(),
vec![from, to],
nonces,
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(&message, &[]);
let tx = PublicTransaction::new(message, witness_set);
// Submit the transaction
let _response = wallet_core
.sequencer_client
.send_tx_public(tx)
.await
.unwrap();
}
Command::MoveDataPublicToPrivate { from, to } => {
let instruction: Instruction = (MOVE_DATA_FUNCTION_ID, vec![]);
let from = from.parse().unwrap();
let to = to.parse().unwrap();
let accounts = vec![
PrivacyPreservingAccount::Public(from),
PrivacyPreservingAccount::PrivateOwned(to),
];
wallet_core
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(instruction).unwrap(),
&program,
)
.await
.unwrap();
}
};
}