refactor program

This commit is contained in:
Sergio Chouhy 2025-08-09 20:25:58 -03:00
parent 51d8ac47cf
commit 6030e54cd7
11 changed files with 105 additions and 108 deletions

View File

@ -1,4 +1,3 @@
// TODO: Consider wrapping `AccountAddress` in a struct. // TODO: Consider wrapping `AccountAddress` in a struct.
pub type AccountAddress = [u8; 32]; pub type AccountAddress = [u8; 32];

View File

@ -1,6 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
//Requests //Requests
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]

View File

@ -31,7 +31,7 @@ pub fn produce_dummy_block(
} }
pub fn produce_dummy_empty_transaction() -> nssa::PublicTransaction { pub fn produce_dummy_empty_transaction() -> nssa::PublicTransaction {
let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id(); let program_id = nssa::program::AUTHENTICATED_TRANSFER_PROGRAM.id();
let addresses = vec![]; let addresses = vec![];
let nonces = vec![]; let nonces = vec![];
let instruction_data = 0; let instruction_data = 0;
@ -42,7 +42,7 @@ pub fn produce_dummy_empty_transaction() -> nssa::PublicTransaction {
nssa::PublicTransaction::new(message, witness_set) nssa::PublicTransaction::new(message, witness_set)
} }
pub fn create_dummy_transaction_native_token_transfer( pub fn create_transaction_native_token_transfer(
from: [u8; 32], from: [u8; 32],
nonce: u128, nonce: u128,
to: [u8; 32], to: [u8; 32],
@ -51,7 +51,7 @@ pub fn create_dummy_transaction_native_token_transfer(
) -> nssa::PublicTransaction { ) -> nssa::PublicTransaction {
let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)]; let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)];
let nonces = vec![nonce]; let nonces = vec![nonce];
let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id(); let program_id = nssa::program::AUTHENTICATED_TRANSFER_PROGRAM.id();
let message = let message =
nssa::public_transaction::Message::new(program_id, addresses, nonces, balance_to_move); nssa::public_transaction::Message::new(program_id, addresses, nonces, balance_to_move);
let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[&signing_key]); let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[&signing_key]);

View File

@ -1,12 +1,6 @@
use nssa_core::{
account::{Account, AccountWithMetadata},
program::{DEFAULT_PROGRAM_ID, ProgramId},
};
use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID};
use risc0_zkvm::{ExecutorEnv, ExecutorEnvBuilder, default_executor};
mod address; mod address;
pub mod error; pub mod error;
pub mod program;
pub mod public_transaction; pub mod public_transaction;
mod signature; mod signature;
mod state; mod state;
@ -17,68 +11,3 @@ pub use signature::PrivateKey;
pub use signature::PublicKey; pub use signature::PublicKey;
pub use signature::Signature; pub use signature::Signature;
pub use state::V01State; pub use state::V01State;
use crate::error::NssaError;
pub const AUTHENTICATED_TRANSFER_PROGRAM: Program = Program {
id: AUTHENTICATED_TRANSFER_ID,
elf: AUTHENTICATED_TRANSFER_ELF,
};
pub struct Program {
id: ProgramId,
elf: &'static [u8],
}
/// Writes inputs to `env_builder` in the order expected by the programs
fn write_inputs(
pre_states: &[AccountWithMetadata],
instruction_data: u128,
env_builder: &mut ExecutorEnvBuilder,
) -> Result<(), NssaError> {
let pre_states = pre_states.to_vec();
env_builder
.write(&pre_states)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
env_builder
.write(&instruction_data)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
Ok(())
}
impl Program {
pub fn id(&self) -> ProgramId {
self.id
}
pub(crate) fn execute(
&self,
pre_states: &[AccountWithMetadata],
instruction_data: u128,
) -> Result<Vec<Account>, NssaError> {
// Write inputs to the program
let mut env_builder = ExecutorEnv::builder();
write_inputs(pre_states, instruction_data, &mut env_builder)?;
let env = env_builder.build().unwrap();
// Execute the program (without proving)
let executor = default_executor();
let session_info = executor
.execute(env, self.elf)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
// Get outputs
let mut post_states: Vec<Account> = session_info
.journal
.decode()
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
// Claim any output account with default program owner field
for account in post_states.iter_mut() {
if account.program_owner == DEFAULT_PROGRAM_ID {
account.program_owner = self.id;
}
}
Ok(post_states)
}
}

71
nssa/src/program.rs Normal file
View File

@ -0,0 +1,71 @@
use nssa_core::{
account::{Account, AccountWithMetadata},
program::{DEFAULT_PROGRAM_ID, ProgramId},
};
use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID};
use risc0_zkvm::{ExecutorEnv, ExecutorEnvBuilder, default_executor};
use crate::error::NssaError;
pub struct Program {
id: ProgramId,
elf: &'static [u8],
}
pub const AUTHENTICATED_TRANSFER_PROGRAM: Program = Program {
id: AUTHENTICATED_TRANSFER_ID,
elf: AUTHENTICATED_TRANSFER_ELF,
};
impl Program {
pub fn id(&self) -> ProgramId {
self.id
}
pub(crate) fn execute(
&self,
pre_states: &[AccountWithMetadata],
instruction_data: u128,
) -> Result<Vec<Account>, NssaError> {
// Write inputs to the program
let mut env_builder = ExecutorEnv::builder();
Self::write_inputs(pre_states, instruction_data, &mut env_builder)?;
let env = env_builder.build().unwrap();
// Execute the program (without proving)
let executor = default_executor();
let session_info = executor
.execute(env, self.elf)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
// Get outputs
let mut post_states: Vec<Account> = session_info
.journal
.decode()
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
// Claim any output account with default program owner field
for account in post_states.iter_mut() {
if account.program_owner == DEFAULT_PROGRAM_ID {
account.program_owner = self.id;
}
}
Ok(post_states)
}
/// Writes inputs to `env_builder` in the order expected by the programs
fn write_inputs(
pre_states: &[AccountWithMetadata],
instruction_data: u128,
env_builder: &mut ExecutorEnvBuilder,
) -> Result<(), NssaError> {
let pre_states = pre_states.to_vec();
env_builder
.write(&pre_states)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
env_builder
.write(&instruction_data)
.map_err(|e| NssaError::ProgramExecutionFailed(e.to_string()))?;
Ok(())
}
}

View File

@ -1,7 +1,4 @@
use nssa_core::{ use nssa_core::{account::Nonce, program::ProgramId};
account::Nonce,
program::ProgramId,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, digest::FixedOutput}; use sha2::{Digest, digest::FixedOutput};

View File

@ -1,5 +1,7 @@
use crate::{ use crate::{
AUTHENTICATED_TRANSFER_PROGRAM, Program, address::Address, error::NssaError, address::Address,
error::NssaError,
program::{AUTHENTICATED_TRANSFER_PROGRAM, Program},
public_transaction::PublicTransaction, public_transaction::PublicTransaction,
}; };
use nssa_core::{ use nssa_core::{
@ -21,7 +23,7 @@ impl V01State {
.map(|(address_value, balance)| { .map(|(address_value, balance)| {
let account = Account { let account = Account {
balance, balance,
program_owner: AUTHENTICATED_TRANSFER_PROGRAM.id, program_owner: AUTHENTICATED_TRANSFER_PROGRAM.id(),
..Account::default() ..Account::default()
}; };
let address = Address::new(address_value); let address = Address::new(address_value);
@ -30,7 +32,7 @@ impl V01State {
.collect(); .collect();
let builtin_programs = HashMap::from([( let builtin_programs = HashMap::from([(
AUTHENTICATED_TRANSFER_PROGRAM.id, AUTHENTICATED_TRANSFER_PROGRAM.id(),
AUTHENTICATED_TRANSFER_PROGRAM, AUTHENTICATED_TRANSFER_PROGRAM,
)]); )]);
@ -155,7 +157,7 @@ mod tests {
) -> PublicTransaction { ) -> PublicTransaction {
let addresses = vec![from, to]; let addresses = vec![from, to];
let nonces = vec![nonce]; let nonces = vec![nonce];
let program_id = AUTHENTICATED_TRANSFER_PROGRAM.id; let program_id = AUTHENTICATED_TRANSFER_PROGRAM.id();
let message = public_transaction::Message::new(program_id, addresses, nonces, balance); let message = public_transaction::Message::new(program_id, addresses, nonces, balance);
let witness_set = public_transaction::WitnessSet::for_message(&message, &[&from_key]); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&from_key]);
PublicTransaction::new(message, witness_set) PublicTransaction::new(message, witness_set)

View File

@ -369,7 +369,7 @@ mod tests {
let sign_key1 = create_signing_key_for_account1(); let sign_key1 = create_signing_key_for_account1();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 10, sign_key1, acc1, 0, acc2, 10, sign_key1,
); );
let result = sequencer.transaction_pre_check(tx); let result = sequencer.transaction_pre_check(tx);
@ -395,7 +395,7 @@ mod tests {
let sign_key2 = create_signing_key_for_account2(); let sign_key2 = create_signing_key_for_account2();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 10, sign_key2, acc1, 0, acc2, 10, sign_key2,
); );
@ -405,7 +405,10 @@ mod tests {
// Signature is not from sender. Execution fails // Signature is not from sender. Execution fails
let result = sequencer.execute_check_transaction_on_state(tx); let result = sequencer.execute_check_transaction_on_state(tx);
assert!(matches!(result, Err(nssa::error::NssaError::ProgramExecutionFailed(_)))); assert!(matches!(
result,
Err(nssa::error::NssaError::ProgramExecutionFailed(_))
));
} }
#[test] #[test]
@ -426,7 +429,7 @@ mod tests {
let sign_key1 = create_signing_key_for_account1(); let sign_key1 = create_signing_key_for_account1();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 10000000, sign_key1, acc1, 0, acc2, 10000000, sign_key1,
); );
// let tx_roots = sequencer.get_tree_roots(); // let tx_roots = sequencer.get_tree_roots();
@ -462,7 +465,7 @@ mod tests {
let sign_key1 = create_signing_key_for_account1(); let sign_key1 = create_signing_key_for_account1();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 100, sign_key1, acc1, 0, acc2, 100, sign_key1,
); );
@ -553,7 +556,7 @@ mod tests {
let sign_key1 = create_signing_key_for_account1(); let sign_key1 = create_signing_key_for_account1();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 100, sign_key1, acc1, 0, acc2, 100, sign_key1,
); );
@ -595,7 +598,7 @@ mod tests {
let sign_key1 = create_signing_key_for_account1(); let sign_key1 = create_signing_key_for_account1();
let tx = common::test_utils::create_dummy_transaction_native_token_transfer( let tx = common::test_utils::create_transaction_native_token_transfer(
acc1, 0, acc2, 100, sign_key1, acc1, 0, acc2, 100, sign_key1,
); );

View File

@ -76,7 +76,7 @@ fn block_to_transactions_map(block: &Block) -> HashMap<TreeHashType, u64> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use tempfile::tempdir; use tempfile::tempdir;
// //
// fn create_dummy_block_with_transaction(block_id: u64) -> (Block, nssa::PublicTransaction) { // fn create_dummy_block_with_transaction(block_id: u64) -> (Block, nssa::PublicTransaction) {

View File

@ -18,7 +18,8 @@ use common::{
use common::rpc_primitives::requests::{ use common::rpc_primitives::requests::{
GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse,
GetLastBlockRequest, GetLastBlockResponse, HelloRequest, HelloResponse, SendTxRequest, SendTxResponse, GetLastBlockRequest, GetLastBlockResponse, HelloRequest, HelloResponse, SendTxRequest,
SendTxResponse,
}; };
use super::{respond, types::err_rpc::RpcErr, JsonHandler}; use super::{respond, types::err_rpc::RpcErr, JsonHandler};
@ -203,7 +204,7 @@ mod tests {
use crate::{rpc_handler, JsonHandler}; use crate::{rpc_handler, JsonHandler};
use common::rpc_primitives::RpcPollingConfig; use common::rpc_primitives::RpcPollingConfig;
use sequencer_core::{ use sequencer_core::{
config::{AccountInitialData, SequencerConfig}, config::{AccountInitialData, SequencerConfig},
SequencerCore, SequencerCore,
@ -260,19 +261,15 @@ mod tests {
let mut sequencer_core = SequencerCore::start_from_config(config); let mut sequencer_core = SequencerCore::start_from_config(config);
let initial_accounts = sequencer_core.sequencer_config.initial_accounts.clone(); let initial_accounts = sequencer_core.sequencer_config.initial_accounts.clone();
let from = nssa::Address::new([1; 32]);
let signing_key = nssa::PrivateKey::new(1); let signing_key = nssa::PrivateKey::new(1);
let to = nssa::Address::new([2; 32]);
let balance_to_move = 10; let balance_to_move = 10;
let tx = common::test_utils::create_transaction_native_token_transfer(
let addresses = vec![from, to]; [1; 32],
let nonces = vec![0]; 0,
let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id(); [2; 32],
let message = balance_to_move,
nssa::public_transaction::Message::new(program_id, addresses, nonces, balance_to_move); signing_key,
let witness_set = );
nssa::public_transaction::WitnessSet::for_message(&message, &[&signing_key]);
let tx = nssa::PublicTransaction::new(message, witness_set);
sequencer_core sequencer_core
.push_tx_into_mempool_pre_check(tx.clone()) .push_tx_into_mempool_pre_check(tx.clone())
@ -501,7 +498,7 @@ mod tests {
], ],
"instruction_data": 10, "instruction_data": 10,
"nonces": [0], "nonces": [0],
"program_id": nssa::AUTHENTICATED_TRANSFER_PROGRAM.id(), "program_id": nssa::program::AUTHENTICATED_TRANSFER_PROGRAM.id(),
}, },
"witness_set": { "witness_set": {
"signatures_and_public_keys": [ "signatures_and_public_keys": [

View File

@ -86,7 +86,7 @@ impl NodeCore {
if let Some(account) = account { if let Some(account) = account {
let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)]; let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)];
let nonces = vec![nonce]; let nonces = vec![nonce];
let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id(); let program_id = nssa::program::AUTHENTICATED_TRANSFER_PROGRAM.id();
let message = nssa::public_transaction::Message::new( let message = nssa::public_transaction::Message::new(
program_id, program_id,
addresses, addresses,