sequencer wip

This commit is contained in:
Sergio Chouhy 2025-07-17 12:46:57 -03:00
parent 196c375d21
commit 34731a9950
6 changed files with 125 additions and 9 deletions

View File

@ -4,3 +4,4 @@ pub type Address = [u32; 8];
pub type Nonce = [u32; 8];
pub type Key = [u32; 8];
pub type AuthenticationPath = [[u32; 8]; 32];
pub type ProgramId = [u32; 8];

View File

@ -5,8 +5,8 @@ use core::{
types::{Address, AuthenticationPath, Commitment, Nullifier},
};
use nssa::program::TransferMultipleProgram;
use sparse_merkle_tree::SparseMerkleTree;
use program_methods::OUTER_ID;
use sparse_merkle_tree::SparseMerkleTree;
fn mint_fresh_account(address: Address) -> Account {
let nonce = [0; 8];

View File

@ -0,0 +1,7 @@
use crate::sequencer_mock::MockedSequencer;
mod sequencer_mock;
fn main() {
let sequencer = MockedSequencer::new();
}

View File

@ -0,0 +1,102 @@
use core::{
account::Account,
types::{Address, Key, Nullifier, ProgramId},
};
use std::collections::{HashMap, HashSet};
use nssa;
use program_methods::{PINATA_ID, TRANSFER_ID, TRANSFER_MULTIPLE_ID};
use sparse_merkle_tree::SparseMerkleTree;
pub struct MockedSequencer {
accounts: HashMap<Address, Account>,
commitment_tree: SparseMerkleTree,
nullifier_set: HashSet<Nullifier>,
deployed_program_ids: HashSet<ProgramId>,
}
const ACCOUNTS_PRIVATE_KEYS: [Key; 5] = [[1; 8], [2; 8], [3; 8], [4; 8], [5; 8]];
const ACCOUNTS_INITIAL_BALANCES: [u128; 5] = [100, 3, 900, 44, 0];
const DEPLOYED_PROGRAM_IDS: [ProgramId; 3] = [TRANSFER_ID, TRANSFER_MULTIPLE_ID, PINATA_ID];
impl MockedSequencer {
pub fn new() -> Self {
let mut accounts: HashMap<Address, Account> = ACCOUNTS_PRIVATE_KEYS
.iter()
.cloned()
.zip(ACCOUNTS_INITIAL_BALANCES)
.map(|(key, initial_balance)| {
let mut this = Account::new_from_private_key(key, [0; 8]);
this.balance = initial_balance;
this
})
.map(|account| (account.address, account))
.collect();
let pinata_account = {
let mut this = Account::new([0xcafe; 8], [0; 8]);
this.balance = 100;
this
};
accounts.insert(pinata_account.address, pinata_account);
let commitment_tree = SparseMerkleTree::new_empty();
let nullifier_set = HashSet::new();
Self {
accounts,
commitment_tree,
nullifier_set,
deployed_program_ids: DEPLOYED_PROGRAM_IDS.iter().collect(),
}
}
pub fn get_account(&self, address: &Address) -> Option<Account> {
self.accounts.get(address).cloned()
}
pub fn invoke_program_public<P: nssa::Program>(
&mut self,
program_id: ProgramId,
input_account_addresses: &[Address],
instruction_data: &P::InstructionData,
) -> Result<(), ()> {
let input_accounts: Vec<Account> = input_account_addresses
.iter()
.map(|address| self.get_account(address).ok_or(|_| ())?)
.collect();
let inputs_outputs = nssa::execute(input_accounts, instruction_data)?;
self.inputs_outputs_are_consistent(&input_accounts, &inputs_outputs)?
}
fn inputs_outputs_are_consistent(
&self,
input_accounts: &[Account],
inputs_outputs: &[Account],
) -> Result<(), ()> {
let num_inputs = input_accounts.len();
if inputs_outputs.len() != num_inputs * 2 {
return Err(());
}
let (claimed_accounts_pre, accounts_post) = inputs_outputs.split_at(num_inputs);
if claimed_accounts_pre != input_accounts {
return Err(());
}
for (account_pre, account_post) in input_accounts.iter().zip(accounts_post) {
if account_pre.address != account_post.address {
return Err(());
}
if account_pre.nonce != account_post.nonce {
return Err(());
}
}
let accounts_pre_total_balance = input_accounts.iter().map(|account| account.balance).sum();
let accounts_post_total_balance = accounts_post.iter().map(|account| account.balance).sum();
if accounts_pre_total_balance != accounts_post_total_balance {
return Err(());
}
return Ok(());
}
}

View File

@ -1,7 +1,11 @@
use risc0_zkvm::{guest::env, serde::to_vec};
use core::{
account::Account, compute_nullifier, hash, input::InputVisibiility, is_in_tree, types::Nonce,
account::Account,
compute_nullifier, hash,
input::InputVisibiility,
is_in_tree,
types::{Nonce, ProgramId},
};
use risc0_zkvm::{guest::env, serde::to_vec};
/// Private execution logic.
/// Circuit for proving correct execution of some program with program id
@ -33,7 +37,7 @@ fn main() {
assert_eq!(output_nonces.len() as u32, num_inputs);
let commitment_tree_root: [u32; 8] = env::read();
let program_id: [u32; 8] = env::read();
let program_id: ProgramId = env::read();
// Verify pre states and post states of accounts are consistent
// with the execution of the `program_id`` program

View File

@ -1,17 +1,19 @@
use serde::{Deserialize, Serialize};
use core::types::ProgramId;
use program_methods::{
PINATA_ELF, PINATA_ID, TRANSFER_ELF, TRANSFER_ID, {TRANSFER_MULTIPLE_ELF, TRANSFER_MULTIPLE_ID},
};
use serde::{Deserialize, Serialize};
pub trait Program {
const PROGRAM_ID: [u32; 8];
const PROGRAM_ID: ProgramId;
const PROGRAM_ELF: &[u8];
type InstructionData: Serialize + for<'de> Deserialize<'de>;
}
pub struct TransferProgram;
impl Program for TransferProgram {
const PROGRAM_ID: [u32; 8] = TRANSFER_ID;
const PROGRAM_ID: ProgramId = TRANSFER_ID;
const PROGRAM_ELF: &[u8] = TRANSFER_ELF;
/// Amount to transfer
type InstructionData = u128;
@ -19,7 +21,7 @@ impl Program for TransferProgram {
pub struct TransferMultipleProgram;
impl Program for TransferMultipleProgram {
const PROGRAM_ID: [u32; 8] = TRANSFER_MULTIPLE_ID;
const PROGRAM_ID: ProgramId = TRANSFER_MULTIPLE_ID;
const PROGRAM_ELF: &[u8] = TRANSFER_MULTIPLE_ELF;
/// Amounts to transfer
type InstructionData = Vec<u128>;
@ -27,7 +29,7 @@ impl Program for TransferMultipleProgram {
pub struct PinataProgram;
impl Program for PinataProgram {
const PROGRAM_ID: [u32; 8] = TRANSFER_MULTIPLE_ID;
const PROGRAM_ID: ProgramId = TRANSFER_MULTIPLE_ID;
const PROGRAM_ELF: &[u8] = TRANSFER_MULTIPLE_ELF;
/// Preimage of target hash to win price
type InstructionData = [u32; 8];