refactor to use privacy tail calls from send_privacy_preserving_tx and add the example runner

This commit is contained in:
Sergio Chouhy
2025-12-12 14:21:07 -03:00
parent 89c1a97798
commit 77fd189010
10 changed files with 119 additions and 23 deletions
+23 -1
View File
@@ -340,7 +340,7 @@ Luckily all that complexity is hidden behind the `wallet_core.send_privacy_prese
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(greeting).unwrap(),
&program,
&program.into(),
)
.await
.unwrap();
@@ -568,6 +568,28 @@ Output:
```
Hola mundo!Hello from tail call
```
## Private tail-calls
There's support for tail calls in privacy preserving executions too. The `run_hello_world_through_tail_call_private.rs` runner walks you through the process of invoking such an execution.
The only difference is that, since the execution is local, the runner will need both programs: the `simple_tail_call` and it's dependency `hello_world`.
Let's use our existing private account with id `8vzkK7vsdrS2gdPhLk72La8X4FJkgJ5kJLUBRbEVkReU`. This one is already owned by the `hello_world` program.
You can test the privacy tail calls with
```bash
cargo run --bin run_hello_world_through_tail_call_private \
$EXAMPLE_PROGRAMS_BUILD_DIR/simple_tail_call.bin \
$EXAMPLE_PROGRAMS_BUILD_DIR/hello_world.bin \
8vzkK7vsdrS2gdPhLk72La8X4FJkgJ5kJLUBRbEVkReU
```
>[!NOTE]
> The above command may take longer than the previous privacy executions because needs to generate proofs of execution of both the `simple_tail_call` and the `hello_world` programs.
Once finished run the following to see the changes
```bash
wallet account sync-private
wallet account get --account-id Private/8vzkK7vsdrS2gdPhLk72La8X4FJkgJ5kJLUBRbEVkReU
```
# 13. Program derived accounts: authorizing accounts through tail calls
@@ -54,7 +54,7 @@ async fn main() {
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(greeting).unwrap(),
&program,
&program.into(),
)
.await
.unwrap();
@@ -0,0 +1,71 @@
use std::collections::HashMap;
use nssa::{
AccountId, ProgramId, PublicTransaction,
privacy_preserving_transaction::circuit::ProgramWithDependencies,
program::Program,
public_transaction::{Message, WitnessSet},
};
use wallet::{PrivacyPreservingAccount, 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_private /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 simple_tail_call program binary
let simple_tail_call_path = std::env::args_os().nth(1).unwrap().into_string().unwrap();
// Second argument is the path to the hello_world program binary
let hello_world_path = std::env::args_os().nth(2).unwrap().into_string().unwrap();
// Third argument is the account_id
let account_id: AccountId = std::env::args_os()
.nth(3)
.unwrap()
.into_string()
.unwrap()
.parse()
.unwrap();
// Load the program and its dependencies (the hellow world program)
let simple_tail_call_bytecode: Vec<u8> = std::fs::read(simple_tail_call_path).unwrap();
let simple_tail_call = Program::new(simple_tail_call_bytecode).unwrap();
let hello_world_bytecode: Vec<u8> = std::fs::read(hello_world_path).unwrap();
let hello_world = Program::new(hello_world_bytecode).unwrap();
let dependencies: HashMap<ProgramId, Program> =
[(hello_world.id(), hello_world)].into_iter().collect();
let program_with_dependencies = ProgramWithDependencies::new(simple_tail_call, dependencies);
let accounts = vec![PrivacyPreservingAccount::PrivateOwned(account_id)];
// Construct and submit the privacy-preserving transaction
let instruction = ();
wallet_core
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(instruction).unwrap(),
&program_with_dependencies,
)
.await
.unwrap();
}
@@ -105,7 +105,7 @@ async fn main() {
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(instruction).unwrap(),
&program,
&program.into(),
)
.await
.unwrap();
@@ -146,7 +146,7 @@ async fn main() {
.send_privacy_preserving_tx(
accounts,
&Program::serialize_instruction(instruction).unwrap(),
&program,
&program.into(),
)
.await
.unwrap();