Sergio Chouhy 4bcffafe27 refactor!: rename nssa crate to lee
BREAKING CHANGE:
- Crate `nssa` renamed to `lee`; update `Cargo.toml` dependencies from `nssa = { workspace = true }` to `lee = { workspace = true }`.
- Crate `nssa_core` renamed to `lee_core`; update similarly.
- Crate `key_protocol` moved under `lee`; update `Cargo.toml` dependencies from `key_protocol = { workspace = true }` to `lee_key_protocol = { workspace = true }`.
- Type `NSSATransaction` (in `common`) renamed to `LeeTransaction`.
- Error type `nssa::error::NssaError` renamed to `lee::error::LeeError`.
- Error type `nssa_core::error::NssaCoreError` renamed to `lee_core::error::LeeCoreError`.
- All `use nssa::` and `use nssa_core::` import paths must be updated to `use lee::` and `use lee_core::` respectively.
- Guest programs must replace `write_nssa_outputs` with `write_lee_outputs`.
- The sequencer RocksDB column family for the chain state was renamed. Existing databases are incompatible and must be wiped before running the new version.
- Domain separators updated: `"NSSA_seed"` → `"LEE_seed"` (key derivation), `"NSSA/v0.2/KDF-SHA256/"` → `"LEE/v0.2/KDF-SHA256/"` (encryption KDF), `"/NSSA/v0.2/AccountId/PDA/"` →
  `"/LEE/v0.2/AccountId/PDA/"` (public PDA address derivation). All previously derived keys, encrypted outputs, and public PDA addresses are invalidated.
2026-06-01 17:11:42 -03:00

160 lines
5.4 KiB
Rust

//! Feature-gated implementation of PPE composition benches.
//!
//! `prove_auth_transfer_in_ppe` is reused by the `verify` criterion bench under
//! `benches/verify.rs` (re-exported via `super::prove_auth_transfer_in_ppe`).
use std::{collections::HashMap, time::Instant};
use lee::{
execute_and_prove,
privacy_preserving_transaction::circuit::{ProgramWithDependencies, Proof},
program::Program,
};
use lee_core::{
InputAccountIdentity, PrivacyPreservingCircuitOutput,
account::{Account, AccountId, AccountWithMetadata},
program::ProgramId,
};
use risc0_zkvm::serde::to_vec;
use super::PpeBenchResult;
const AUTH_TRANSFER_ID: ProgramId = lee::program_methods::AUTHENTICATED_TRANSFER_ID;
const AUTH_TRANSFER_ELF: &[u8] = lee::program_methods::AUTHENTICATED_TRANSFER_ELF;
/// `chain_caller` bytecode shipped at `artifacts/test_program_methods/chain_caller.bin`.
/// Loaded at compile time so we don't need a dev-dependency on `test_program_methods`.
const CHAIN_CALLER_ELF: &[u8] =
include_bytes!("../../../../artifacts/test_program_methods/chain_caller.bin");
pub fn run_auth_transfer_in_ppe() -> PpeBenchResult {
let label = "auth_transfer Transfer in PPE".to_owned();
let started = Instant::now();
match prove_auth_transfer_in_ppe() {
Ok((_out, proof)) => {
let prove_ms = started.elapsed().as_secs_f64() * 1_000.0;
PpeBenchResult {
label,
chain_depth: 0,
prove_wall_ms: Some(prove_ms),
proof_bytes: Some(proof.into_inner().len()),
error: None,
}
}
Err(err) => PpeBenchResult {
label,
chain_depth: 0,
prove_wall_ms: None,
proof_bytes: None,
error: Some(err.to_string()),
},
}
}
pub fn prove_auth_transfer_in_ppe() -> anyhow::Result<(PrivacyPreservingCircuitOutput, Proof)> {
let program = Program::new(AUTH_TRANSFER_ELF.to_vec())?;
let pwd = ProgramWithDependencies::from(program);
// For PPE to allow the sender's balance to be decremented by this
// program, the sender must already be claimed by auth_transfer.
// Recipient stays default-owned so the first call can claim it.
let sender = AccountWithMetadata {
account: Account {
program_owner: AUTH_TRANSFER_ID,
balance: 1_000_000,
..Account::default()
},
is_authorized: true,
account_id: AccountId::new([1; 32]),
};
let recipient = AccountWithMetadata {
account: Account::default(),
is_authorized: true,
account_id: AccountId::new([2; 32]),
};
let pre_states = vec![sender, recipient];
let instruction = authenticated_transfer_core::Instruction::Transfer { amount: 5_000 };
let instruction_data = to_vec(&instruction)?;
let account_identities = vec![InputAccountIdentity::Public; pre_states.len()];
Ok(execute_and_prove(
pre_states,
instruction_data,
account_identities,
&pwd,
)?)
}
pub fn run_chain_caller(depth: u32) -> PpeBenchResult {
let label = format!("chain_caller depth={depth}");
let started = Instant::now();
match prove_chain_caller(depth) {
Ok((_out, proof)) => {
let prove_ms = started.elapsed().as_secs_f64() * 1_000.0;
PpeBenchResult {
label,
chain_depth: depth as usize,
prove_wall_ms: Some(prove_ms),
proof_bytes: Some(proof.into_inner().len()),
error: None,
}
}
Err(err) => PpeBenchResult {
label,
chain_depth: depth as usize,
prove_wall_ms: None,
proof_bytes: None,
error: Some(err.to_string()),
},
}
}
fn prove_chain_caller(
num_chain_calls: u32,
) -> anyhow::Result<(PrivacyPreservingCircuitOutput, Proof)> {
let chain_caller = Program::new(CHAIN_CALLER_ELF.to_vec())?;
let auth_transfer = Program::new(AUTH_TRANSFER_ELF.to_vec())?;
let mut deps = HashMap::new();
deps.insert(AUTH_TRANSFER_ID, auth_transfer);
let pwd = ProgramWithDependencies::new(chain_caller, deps);
// Both accounts pre-claimed by auth_transfer. chain_caller doesn't
// track recipient's post-claim program_owner, so a default recipient
// would cause a state mismatch on subsequent chained calls.
let recipient_pre = AccountWithMetadata {
account: Account {
program_owner: AUTH_TRANSFER_ID,
..Account::default()
},
is_authorized: true,
account_id: AccountId::new([2; 32]),
};
let sender_pre = AccountWithMetadata {
account: Account {
program_owner: AUTH_TRANSFER_ID,
balance: 1_000_000,
..Account::default()
},
is_authorized: true,
account_id: AccountId::new([1; 32]),
};
// chain_caller expects pre_states = [recipient, sender].
let pre_states = vec![recipient_pre, sender_pre];
let balance: u128 = 1;
let pda_seed: Option<lee_core::program::PdaSeed> = None;
let instruction = (balance, AUTH_TRANSFER_ID, num_chain_calls, pda_seed);
let instruction_data = to_vec(&instruction)?;
let account_identities = vec![InputAccountIdentity::Public; pre_states.len()];
Ok(execute_and_prove(
pre_states,
instruction_data,
account_identities,
&pwd,
)?)
}