refactor programs. Add builtin programs. Implement account claim logic

This commit is contained in:
Sergio Chouhy 2025-08-08 16:19:50 -03:00
parent 3dfcb47534
commit 002ad048b0
12 changed files with 114 additions and 387 deletions

View File

@ -4,7 +4,7 @@ use mempoolitem::MemPoolItem;
pub mod mempoolitem; pub mod mempoolitem;
pub struct MemPool<Item: MemPoolItem> { pub struct MemPool<Item> {
items: VecDeque<Item>, items: VecDeque<Item>,
} }

View File

@ -1,3 +0,0 @@
pub(crate) struct Commitment {
value: [u8; 32],
}

View File

@ -1,8 +1,3 @@
mod commitment;
mod nullifier;
pub(crate) use commitment::Commitment;
pub(crate) use nullifier::Nullifier;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::program::ProgramId; use crate::program::ProgramId;
@ -27,6 +22,8 @@ pub struct AccountWithMetadata {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::program::DEFAULT_PROGRAM_ID;
use super::*; use super::*;
#[test] #[test]
@ -54,6 +51,6 @@ mod tests {
fn test_default_program_owner_account_data_creation() { fn test_default_program_owner_account_data_creation() {
let new_acc = Account::default(); let new_acc = Account::default();
assert_eq!(new_acc.program_owner, [0; 8]); assert_eq!(new_acc.program_owner, DEFAULT_PROGRAM_ID);
} }
} }

View File

@ -1,3 +0,0 @@
pub(crate) struct Nullifier {
value: [u8; 32]
}

View File

@ -3,12 +3,11 @@ use serde::{Deserialize, Serialize};
use crate::account::{Account, AccountWithMetadata}; use crate::account::{Account, AccountWithMetadata};
pub type ProgramId = [u32; 8]; pub type ProgramId = [u32; 8];
pub const DEFAULT_PROGRAM_ID: ProgramId = [0; 8];
/// A trait to be implemented by inner programs. pub struct Program {
pub trait Program { pub id: ProgramId,
const PROGRAM_ID: ProgramId; pub elf: &'static [u8],
const PROGRAM_ELF: &[u8];
type InstructionData: Serialize + for<'de> Deserialize<'de>;
} }
/// Validates well-behaved program execution /// Validates well-behaved program execution

View File

@ -1,6 +1,6 @@
use nssa_core::{ use nssa_core::{
account::{Account, AccountWithMetadata}, account::{Account, AccountWithMetadata},
program::ProgramId, program::{DEFAULT_PROGRAM_ID, ProgramId},
}; };
use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID}; use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID};
use risc0_zkvm::{ExecutorEnv, ExecutorEnvBuilder, default_executor}; use risc0_zkvm::{ExecutorEnv, ExecutorEnvBuilder, default_executor};
@ -16,17 +16,15 @@ pub use public_transaction::PublicTransaction;
pub use signature::PrivateKey; pub use signature::PrivateKey;
pub use state::V01State; pub use state::V01State;
pub struct AuthenticatedTransferProgram; pub const AUTHENTICATED_TRANSFER_PROGRAM: Program = Program {
impl Program for AuthenticatedTransferProgram { id: AUTHENTICATED_TRANSFER_ID,
const PROGRAM_ID: ProgramId = AUTHENTICATED_TRANSFER_ID; elf: AUTHENTICATED_TRANSFER_ELF,
const PROGRAM_ELF: &[u8] = AUTHENTICATED_TRANSFER_ELF; };
type InstructionData = u128;
}
/// Writes inputs to `env_builder` in the order expected by the programs /// Writes inputs to `env_builder` in the order expected by the programs
fn write_inputs<P: Program>( fn write_inputs(
pre_states: &[AccountWithMetadata], pre_states: &[AccountWithMetadata],
instruction_data: P::InstructionData, instruction_data: u128,
env_builder: &mut ExecutorEnvBuilder, env_builder: &mut ExecutorEnvBuilder,
) -> Result<(), ()> { ) -> Result<(), ()> {
let pre_states = pre_states.to_vec(); let pre_states = pre_states.to_vec();
@ -35,19 +33,29 @@ fn write_inputs<P: Program>(
Ok(()) Ok(())
} }
fn execute_public<P: Program>( fn execute_public(
pre_states: &[AccountWithMetadata], pre_states: &[AccountWithMetadata],
instruction_data: P::InstructionData, instruction_data: u128,
program: &Program,
) -> Result<Vec<Account>, ()> { ) -> Result<Vec<Account>, ()> {
// Write inputs to the program // Write inputs to the program
let mut env_builder = ExecutorEnv::builder(); let mut env_builder = ExecutorEnv::builder();
write_inputs::<P>(pre_states, instruction_data, &mut env_builder)?; write_inputs(pre_states, instruction_data, &mut env_builder)?;
let env = env_builder.build().unwrap(); let env = env_builder.build().unwrap();
// Execute the program (without proving) // Execute the program (without proving)
let executor = default_executor(); let executor = default_executor();
let session_info = executor.execute(env, P::PROGRAM_ELF).map_err(|_| ())?; let session_info = executor.execute(env, program.elf).map_err(|_| ())?;
// Get (inputs and) outputs // Get outputs
session_info.journal.decode().map_err(|_| ()) let mut post_states: Vec<Account> = session_info.journal.decode().map_err(|_| ())?;
// 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 = program.id;
}
}
Ok(post_states)
} }

View File

@ -1,32 +1,41 @@
use crate::{ use crate::{
AuthenticatedTransferProgram, address::Address, execute_public, AUTHENTICATED_TRANSFER_PROGRAM, address::Address, execute_public,
public_transaction::PublicTransaction, public_transaction::PublicTransaction,
}; };
use nssa_core::{ use nssa_core::{
account::{Account, AccountWithMetadata}, account::{Account, AccountWithMetadata},
program::{Program, validate_constraints}, program::{Program, ProgramId, validate_constraints},
}; };
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
pub struct V01State { pub struct V01State {
public_state: HashMap<Address, Account>, public_state: HashMap<Address, Account>,
builtin_programs: HashMap<ProgramId, Program>,
} }
impl V01State { impl V01State {
pub fn new_with_genesis_accounts(initial_data: &[([u8; 32], u128)]) -> Self { pub fn new_with_genesis_accounts(initial_data: &[([u8; 32], u128)]) -> Self {
// TODO:: remove this assert?
let public_state = initial_data let public_state = initial_data
.to_owned() .to_owned()
.into_iter() .into_iter()
.map(|(address_value, balance)| { .map(|(address_value, balance)| {
let mut account = Account::default(); let mut account = Account::default();
account.balance = balance; account.balance = balance;
account.program_owner = AuthenticatedTransferProgram::PROGRAM_ID; account.program_owner = AUTHENTICATED_TRANSFER_PROGRAM.id;
let address = Address::new(address_value); let address = Address::new(address_value);
(address, account) (address, account)
}) })
.collect(); .collect();
Self { public_state }
let builtin_programs = HashMap::from([(
AUTHENTICATED_TRANSFER_PROGRAM.id,
AUTHENTICATED_TRANSFER_PROGRAM,
)]);
Self {
public_state,
builtin_programs,
}
} }
pub fn transition_from_public_transaction(&mut self, tx: &PublicTransaction) -> Result<(), ()> { pub fn transition_from_public_transaction(&mut self, tx: &PublicTransaction) -> Result<(), ()> {
@ -108,20 +117,19 @@ impl V01State {
// Check the `program_id` corresponds to a built-in program // Check the `program_id` corresponds to a built-in program
// Only allowed program so far is the authenticated transfer program // Only allowed program so far is the authenticated transfer program
if message.program_id != AuthenticatedTransferProgram::PROGRAM_ID { let Some(program) = self.builtin_programs.get(&message.program_id) else {
return Err(()); return Err(());
} };
// // Execute program // // Execute program
let post_states = let post_states =
execute_public::<AuthenticatedTransferProgram>(&pre_states, message.instruction_data) execute_public(&pre_states, message.instruction_data, program).map_err(|_| ())?;
.map_err(|_| ())?;
// Verify execution corresponds to a well-behaved program. // Verify execution corresponds to a well-behaved program.
// See the # Programs section for the definition of the `validate_constraints` method. // See the # Programs section for the definition of the `validate_constraints` method.
validate_constraints(&pre_states, &post_states, message.program_id).map_err(|_| ())?; validate_constraints(&pre_states, &post_states, message.program_id).map_err(|_| ())?;
if (post_states.len() != message.addresses.len()) { if post_states.len() != message.addresses.len() {
return Err(()); return Err(());
} }
@ -148,7 +156,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 = AuthenticatedTransferProgram::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)
@ -157,44 +165,77 @@ mod tests {
#[test] #[test]
fn test_1() { fn test_1() {
let initial_data = [([1; 32], 100)]; let initial_data = [([1; 32], 100)];
let mut genesis_state = V01State::new_with_genesis_accounts(&initial_data); let mut state = V01State::new_with_genesis_accounts(&initial_data);
let from = Address::new(initial_data[0].0.clone()); let from = Address::new(initial_data[0].0.clone());
let from_key = PrivateKey(1); let from_key = PrivateKey(1);
let to = Address::new([2; 32]); let to = Address::new([2; 32]);
let balance_to_move = 5; let balance_to_move = 5;
let tx = let tx =
transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move); transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move);
let _ = genesis_state.transition_from_public_transaction(&tx); state.transition_from_public_transaction(&tx).unwrap();
assert_eq!(
genesis_state.get_account_by_address(&to).balance, assert_eq!(state.get_account_by_address(&to).balance, 5);
balance_to_move assert_eq!(state.get_account_by_address(&from).balance, 95);
); assert_eq!(state.get_account_by_address(&from).nonce, 1);
assert_eq!( assert_eq!(state.get_account_by_address(&to).nonce, 0);
genesis_state.get_account_by_address(&from).balance,
initial_data[0].1 - balance_to_move
);
assert_eq!(genesis_state.get_account_by_address(&from).nonce, 1);
assert_eq!(genesis_state.get_account_by_address(&to).nonce, 0);
} }
#[test] #[test]
fn test_2() { fn test_2() {
let initial_data = [([1; 32], 100), ([99; 32], 200)]; let initial_data = [([1; 32], 100), ([99; 32], 200)];
let mut genesis_state = V01State::new_with_genesis_accounts(&initial_data); let mut state = V01State::new_with_genesis_accounts(&initial_data);
let from = Address::new(initial_data[1].0.clone()); let from = Address::new(initial_data[1].0.clone());
let from_key = PrivateKey(99); let from_key = PrivateKey(99);
let to = Address::new(initial_data[0].0.clone()); let to = Address::new(initial_data[0].0.clone());
let balance_to_move = 8; let balance_to_move = 8;
let to_previous_balance = genesis_state.get_account_by_address(&to).balance; let to_previous_balance = state.get_account_by_address(&to).balance;
let tx = let tx =
transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move); transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move);
let _ = genesis_state.transition_from_public_transaction(&tx); state.transition_from_public_transaction(&tx).unwrap();
assert_eq!(genesis_state.get_account_by_address(&to).balance, 108);
assert_eq!( assert_eq!(state.get_account_by_address(&to).balance, 108);
genesis_state.get_account_by_address(&from).balance, assert_eq!(state.get_account_by_address(&from).balance, 192);
initial_data[1].1 - balance_to_move assert_eq!(state.get_account_by_address(&from).nonce, 1);
assert_eq!(state.get_account_by_address(&to).nonce, 0);
}
#[test]
fn test_3() {
let initial_data = [([1; 32], 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data);
let address_1 = Address::new(initial_data[0].0.clone());
let key_1 = PrivateKey(1);
let address_2 = Address::new([2; 32]);
let key_2 = PrivateKey(2);
let address_3 = Address::new([3; 32]);
let balance_to_move = 5;
let tx = transfer_transaction_for_tests(
address_1.clone(),
key_1,
0,
address_2.clone(),
balance_to_move,
); );
assert_eq!(genesis_state.get_account_by_address(&from).nonce, 1); state.transition_from_public_transaction(&tx).unwrap();
assert_eq!(genesis_state.get_account_by_address(&to).nonce, 0);
let balance_to_move = 3;
let tx = transfer_transaction_for_tests(
address_2.clone(),
key_2,
0,
address_3.clone(),
balance_to_move,
);
state.transition_from_public_transaction(&tx).unwrap();
assert_eq!(state.get_account_by_address(&address_1).balance, 95);
assert_eq!(state.get_account_by_address(&address_2).balance, 2);
assert_eq!(state.get_account_by_address(&address_3).balance, 3);
assert_eq!(state.get_account_by_address(&address_1).nonce, 1);
assert_eq!(state.get_account_by_address(&address_2).nonce, 1);
assert_eq!(state.get_account_by_address(&address_3).nonce, 0);
} }
} }

View File

@ -202,7 +202,7 @@ mod tests {
} }
fn create_dummy_transaction() -> nssa::PublicTransaction { fn create_dummy_transaction() -> nssa::PublicTransaction {
let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id;
let addresses = vec![]; let addresses = vec![];
let nonces = vec![]; let nonces = vec![];
let instruction_data = 0; let instruction_data = 0;
@ -223,7 +223,7 @@ mod tests {
) -> 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::AuthenticatedTransferProgram::PROGRAM_ID; let program_id = nssa::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 = let witness_set =

View File

@ -1,4 +1,4 @@
use common::{merkle_tree_public::TreeHashType, transaction::AuthenticatedTransaction}; use common::merkle_tree_public::TreeHashType;
use mempool::mempoolitem::MemPoolItem; use mempool::mempoolitem::MemPoolItem;
pub struct MempoolTransaction { pub struct MempoolTransaction {

View File

@ -1,314 +0,0 @@
use accounts::account_core::address::AccountAddress;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct AccountPublicData {
pub balance: u64,
pub address: AccountAddress,
nonce: u64,
}
impl AccountPublicData {
pub fn new(address: AccountAddress) -> Self {
Self {
balance: 0,
nonce: 0,
address,
}
}
fn new_with_balance(address: AccountAddress, balance: u64) -> Self {
Self {
balance,
address,
nonce: 0,
}
}
}
#[derive(Debug, Clone)]
pub struct SequencerAccountsStore {
accounts: HashMap<AccountAddress, AccountPublicData>,
}
impl SequencerAccountsStore {
pub fn new(initial_accounts: &[(AccountAddress, u64)]) -> Self {
let mut accounts = HashMap::new();
for (account_addr, balance) in initial_accounts {
accounts.insert(
*account_addr,
AccountPublicData::new_with_balance(*account_addr, *balance),
);
}
Self { accounts }
}
///Register new account in accounts store
///
///Starts with zero public balance
pub fn register_account(&mut self, account_addr: AccountAddress) {
self.accounts
.insert(account_addr, AccountPublicData::new(account_addr));
}
///Check, if `account_addr` present in account store
pub fn contains_account(&self, account_addr: &AccountAddress) -> bool {
self.accounts.contains_key(account_addr)
}
///Check `account_addr` balance,
///
///returns 0, if account address not found
pub fn get_account_balance(&self, account_addr: &AccountAddress) -> u64 {
self.accounts
.get(account_addr)
.map(|acc| acc.balance)
.unwrap_or(0)
}
pub fn get_account_nonce(&self, account_addr: &AccountAddress) -> u64 {
self.accounts
.get(account_addr)
.map(|acc| acc.nonce)
.unwrap_or(0)
}
///Update `account_addr` balance,
///
/// returns 0, if account address not found, otherwise returns previous balance
///
/// Also, if account was not previously found, sets it with zero balance
pub fn set_account_balance(&mut self, account_addr: &AccountAddress, new_balance: u64) -> u64 {
let acc_data = self.accounts.get_mut(account_addr);
if let Some(acc_data) = acc_data {
let old_balance = acc_data.balance;
acc_data.balance = new_balance;
old_balance
} else {
self.register_account(*account_addr);
let acc = self.accounts.get_mut(account_addr).unwrap();
acc.balance = new_balance;
0
}
}
///Update `account_addr` nonce,
///
/// Returns previous nonce
pub fn increase_nonce(&mut self, account_addr: &AccountAddress) -> u64 {
if let Some(acc_data) = self.accounts.get_mut(account_addr) {
let old_nonce = acc_data.nonce;
acc_data.nonce += 1;
old_nonce
} else {
self.register_account(*account_addr);
self.increase_nonce(account_addr)
}
}
///Remove account from storage
///
/// Fails, if `balance` is != 0
///
/// Returns `Option<AccountAddress>` which is `None` if `account_addr` vere not present in store
pub fn unregister_account(
&mut self,
account_addr: AccountAddress,
) -> Result<Option<AccountAddress>> {
if self.get_account_balance(&account_addr) == 0 {
Ok(self.accounts.remove(&account_addr).map(|data| data.address))
} else {
anyhow::bail!("Chain consistency violation: It is forbidden to remove account with nonzero balance");
}
}
///Number of accounts present in store
pub fn len(&self) -> usize {
self.accounts.len()
}
///Is accounts store empty
pub fn is_empty(&self) -> bool {
self.accounts.is_empty()
}
}
impl Default for SequencerAccountsStore {
fn default() -> Self {
Self::new(&[])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_zero_balance_account_data_creation() {
let new_acc = AccountPublicData::new([1; 32]);
assert_eq!(new_acc.balance, 0);
assert_eq!(new_acc.address, [1; 32]);
}
#[test]
fn test_zero_nonce_account_data_creation() {
let new_acc = AccountPublicData::new([1; 32]);
assert_eq!(new_acc.nonce, 0);
}
#[test]
fn test_non_zero_balance_account_data_creation() {
let new_acc = AccountPublicData::new_with_balance([1; 32], 10);
assert_eq!(new_acc.balance, 10);
assert_eq!(new_acc.address, [1; 32]);
}
#[test]
fn test_zero_nonce_account_data_creation_with_balance() {
let new_acc = AccountPublicData::new_with_balance([1; 32], 10);
assert_eq!(new_acc.nonce, 0);
}
#[test]
fn default_account_sequencer_store() {
let seq_acc_store = SequencerAccountsStore::default();
assert!(seq_acc_store.accounts.is_empty());
}
#[test]
fn account_sequencer_store_register_acc() {
let mut seq_acc_store = SequencerAccountsStore::default();
seq_acc_store.register_account([1; 32]);
assert!(seq_acc_store.contains_account(&[1; 32]));
let acc_balance = seq_acc_store.get_account_balance(&[1; 32]);
assert_eq!(acc_balance, 0);
}
#[test]
fn account_sequencer_store_unregister_acc_not_present() {
let mut seq_acc_store = SequencerAccountsStore::default();
seq_acc_store.register_account([1; 32]);
let rem_res = seq_acc_store.unregister_account([2; 32]).unwrap();
assert!(rem_res.is_none());
}
#[test]
fn account_sequencer_store_unregister_acc_not_zero_balance() {
let mut seq_acc_store = SequencerAccountsStore::new(&[([1; 32], 12), ([2; 32], 100)]);
let rem_res = seq_acc_store.unregister_account([1; 32]);
assert!(rem_res.is_err());
}
#[test]
fn account_sequencer_store_unregister_acc() {
let mut seq_acc_store = SequencerAccountsStore::default();
seq_acc_store.register_account([1; 32]);
assert!(seq_acc_store.contains_account(&[1; 32]));
seq_acc_store.unregister_account([1; 32]).unwrap().unwrap();
assert!(!seq_acc_store.contains_account(&[1; 32]));
}
#[test]
fn account_sequencer_store_with_preset_accounts_1() {
let seq_acc_store = SequencerAccountsStore::new(&[([1; 32], 12), ([2; 32], 100)]);
assert!(seq_acc_store.contains_account(&[1; 32]));
assert!(seq_acc_store.contains_account(&[2; 32]));
let acc_balance = seq_acc_store.get_account_balance(&[1; 32]);
assert_eq!(acc_balance, 12);
let acc_balance = seq_acc_store.get_account_balance(&[2; 32]);
assert_eq!(acc_balance, 100);
}
#[test]
fn account_sequencer_store_with_preset_accounts_2() {
let seq_acc_store =
SequencerAccountsStore::new(&[([6; 32], 120), ([7; 32], 15), ([8; 32], 10)]);
assert!(seq_acc_store.contains_account(&[6; 32]));
assert!(seq_acc_store.contains_account(&[7; 32]));
assert!(seq_acc_store.contains_account(&[8; 32]));
let acc_balance = seq_acc_store.get_account_balance(&[6; 32]);
assert_eq!(acc_balance, 120);
let acc_balance = seq_acc_store.get_account_balance(&[7; 32]);
assert_eq!(acc_balance, 15);
let acc_balance = seq_acc_store.get_account_balance(&[8; 32]);
assert_eq!(acc_balance, 10);
}
#[test]
fn account_sequencer_store_fetch_unknown_account() {
let seq_acc_store =
SequencerAccountsStore::new(&[([6; 32], 120), ([7; 32], 15), ([8; 32], 10)]);
let acc_balance = seq_acc_store.get_account_balance(&[9; 32]);
assert_eq!(acc_balance, 0);
}
#[test]
fn account_sequencer_store_is_empty_test() {
let seq_acc_store = SequencerAccountsStore::default();
assert!(seq_acc_store.is_empty());
}
#[test]
fn account_sequencer_store_set_balance_to_unknown_account() {
let mut seq_acc_store = SequencerAccountsStore::default();
let ret = seq_acc_store.set_account_balance(&[1; 32], 100);
assert_eq!(ret, 0);
assert!(seq_acc_store.contains_account(&[1; 32]));
assert_eq!(seq_acc_store.get_account_balance(&[1; 32]), 100);
}
#[test]
fn test_increase_nonce() {
let mut account_store = SequencerAccountsStore::default();
let address = [1; 32];
let first_nonce = account_store.increase_nonce(&address);
assert_eq!(first_nonce, 0);
let second_nonce = account_store.increase_nonce(&address);
assert_eq!(second_nonce, 1);
}
}

View File

@ -81,13 +81,15 @@ mod tests {
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) {
let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; let program_id = nssa::AUTHENTICATED_TRANSFER_PROGRAM.id;
let addresses = vec![]; let addresses = vec![];
let nonces = vec![]; let nonces = vec![];
let instruction_data = 0; let instruction_data = 0;
let message = nssa::public_transaction::Message::new(program_id, addresses, nonces, instruction_data); let message =
nssa::public_transaction::Message::new(program_id, addresses, nonces, instruction_data);
let private_key = nssa::PrivateKey::new(1); let private_key = nssa::PrivateKey::new(1);
let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[private_key]); let witness_set =
nssa::public_transaction::WitnessSet::for_message(&message, &[private_key]);
let tx = nssa::PublicTransaction::new(message, witness_set); let tx = nssa::PublicTransaction::new(message, witness_set);
( (
Block { Block {

View File

@ -267,7 +267,7 @@ mod tests {
let addresses = vec![from, to]; let addresses = vec![from, to];
let nonces = vec![0]; let nonces = vec![0];
let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; let program_id = nssa::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 = let witness_set =
@ -497,7 +497,7 @@ mod tests {
], ],
"instruction_data": 10, "instruction_data": 10,
"nonces": [0], "nonces": [0],
"program_id": nssa::AuthenticatedTransferProgram::PROGRAM_ID, "program_id": nssa::AUTHENTICATED_TRANSFER_PROGRAM.id,
}, },
"witness_set": { "witness_set": {
"signatures_and_public_keys": [ "signatures_and_public_keys": [