From 7f075fcdd3104d4138176651d6e542e265f032b1 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Sat, 25 Oct 2025 00:30:04 -0300 Subject: [PATCH 1/4] wip --- sequencer_core/src/lib.rs | 40 ++++++++++++++----- .../src/sequencer_store/block_store.rs | 6 +-- sequencer_core/src/sequencer_store/mod.rs | 19 +++------ sequencer_runner/Cargo.toml | 1 + storage/src/lib.rs | 3 +- 5 files changed, 41 insertions(+), 28 deletions(-) diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 7366471..6bd10de 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -12,6 +12,8 @@ use mempool::MemPool; use sequencer_store::SequecerChainStore; use serde::{Deserialize, Serialize}; +use crate::sequencer_store::block_store::block_to_transactions_map; + pub mod config; pub mod sequencer_store; @@ -53,19 +55,39 @@ impl SequencerCore { initial_commitments.push(comm); } - Self { - store: SequecerChainStore::new_with_genesis( - &config.home, - config.genesis_id, - config.is_genesis_random, - &config.initial_accounts, - &initial_commitments, - nssa::PrivateKey::try_new(config.signing_key).unwrap(), - ), + let store = SequecerChainStore::new_with_genesis( + &config.home, + config.genesis_id, + config.is_genesis_random, + &config.initial_accounts, + &initial_commitments, + nssa::PrivateKey::try_new(config.signing_key).unwrap(), + ); + + let mut block_id = config.genesis_id; + + let mut this = Self { + store, mempool: MemPool::default(), chain_height: config.genesis_id, sequencer_config: config, + }; + + loop { + let Ok(block) = this.store.block_store.get_block_at_id(block_id) else { + break; + }; + for encoded_transaction in block.body.transactions { + let transaction = NSSATransaction::try_from(&encoded_transaction).unwrap(); + let transaction = this.transaction_pre_check(transaction).unwrap(); + this.execute_check_transaction_on_state(transaction).unwrap(); + this.store.block_store.tx_hash_to_block_map.insert(encoded_transaction.hash(), block_id); + + } + block_id +=1; } + + this } pub fn transaction_pre_check( diff --git a/sequencer_core/src/sequencer_store/block_store.rs b/sequencer_core/src/sequencer_store/block_store.rs index e1dbb2b..6fd9fb7 100644 --- a/sequencer_core/src/sequencer_store/block_store.rs +++ b/sequencer_core/src/sequencer_store/block_store.rs @@ -7,7 +7,7 @@ use storage::RocksDBIO; pub struct SequecerBlockStore { dbio: RocksDBIO, // TODO: Consider adding the hashmap to the database for faster recovery. - tx_hash_to_block_map: HashMap, + pub tx_hash_to_block_map: HashMap, pub genesis_id: u64, pub signing_key: nssa::PrivateKey, } @@ -28,7 +28,7 @@ impl SequecerBlockStore { HashMap::new() }; - let dbio = RocksDBIO::new(location, genesis_block)?; + let dbio = RocksDBIO::open_or_create(location, genesis_block)?; let genesis_id = dbio.get_meta_first_block_in_db()?; @@ -71,7 +71,7 @@ impl SequecerBlockStore { } } -fn block_to_transactions_map(block: &Block) -> HashMap { +pub(crate) fn block_to_transactions_map(block: &Block) -> HashMap { block .body .transactions diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index 4f18405..f6ca478 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -1,11 +1,11 @@ use std::path::Path; use block_store::SequecerBlockStore; -use common::block::HashableBlockData; +use common::{block::HashableBlockData, transaction::{self, NSSATransaction}}; use nssa::{self, Address}; use rand::{RngCore, rngs::OsRng}; -use crate::config::AccountInitialData; +use crate::{config::AccountInitialData, sequencer_store::block_store::block_to_transactions_map}; pub mod block_store; @@ -39,21 +39,11 @@ impl SequecerChainStore { this }; - let mut data = [0; 32]; - let mut prev_block_hash = [0; 32]; - - if is_genesis_random { - OsRng.fill_bytes(&mut data); - OsRng.fill_bytes(&mut prev_block_hash); - } - - let curr_time = chrono::Utc::now().timestamp_millis() as u64; - let hashable_data = HashableBlockData { block_id: genesis_id, transactions: vec![], - prev_block_hash, - timestamp: curr_time, + prev_block_hash: [0; 32], + timestamp: 0, }; let genesis_block = hashable_data.into_block(&signing_key); @@ -67,6 +57,7 @@ impl SequecerChainStore { ) .unwrap(); + Self { state, block_store } } } diff --git a/sequencer_runner/Cargo.toml b/sequencer_runner/Cargo.toml index 4da788d..2f105ee 100644 --- a/sequencer_runner/Cargo.toml +++ b/sequencer_runner/Cargo.toml @@ -22,6 +22,7 @@ path = "../sequencer_rpc" [dependencies.sequencer_core] path = "../sequencer_core" +features = ["testnet"] [dependencies.common] path = "../common" diff --git a/storage/src/lib.rs b/storage/src/lib.rs index d69c521..cbce767 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -44,7 +44,7 @@ pub struct RocksDBIO { } impl RocksDBIO { - pub fn new(path: &Path, start_block: Option) -> DbResult { + pub fn open_or_create(path: &Path, start_block: Option) -> DbResult { let mut cf_opts = Options::default(); cf_opts.set_max_write_buffer_number(16); //ToDo: Add more column families for different data @@ -74,7 +74,6 @@ impl RocksDBIO { let block_id = block.header.block_id; dbio.put_meta_first_block_in_db(block)?; dbio.put_meta_is_first_block_set()?; - dbio.put_meta_last_block_in_db(block_id)?; Ok(dbio) From 1ad93c2977e5e68e8b25d1cf28c78dfe9a666880 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 27 Oct 2025 16:04:12 -0300 Subject: [PATCH 2/4] fmt --- sequencer_core/src/lib.rs | 11 +++++++---- sequencer_core/src/sequencer_store/mod.rs | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 6bd10de..ac4fe72 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -80,11 +80,14 @@ impl SequencerCore { for encoded_transaction in block.body.transactions { let transaction = NSSATransaction::try_from(&encoded_transaction).unwrap(); let transaction = this.transaction_pre_check(transaction).unwrap(); - this.execute_check_transaction_on_state(transaction).unwrap(); - this.store.block_store.tx_hash_to_block_map.insert(encoded_transaction.hash(), block_id); - + this.execute_check_transaction_on_state(transaction) + .unwrap(); + this.store + .block_store + .tx_hash_to_block_map + .insert(encoded_transaction.hash(), block_id); } - block_id +=1; + block_id += 1; } this diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index f6ca478..1081960 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -1,7 +1,10 @@ use std::path::Path; use block_store::SequecerBlockStore; -use common::{block::HashableBlockData, transaction::{self, NSSATransaction}}; +use common::{ + block::HashableBlockData, + transaction::{self, NSSATransaction}, +}; use nssa::{self, Address}; use rand::{RngCore, rngs::OsRng}; @@ -57,7 +60,6 @@ impl SequecerChainStore { ) .unwrap(); - Self { state, block_store } } } From 6b7560901262437e23d0b3a0f956967953a7132a Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 27 Oct 2025 20:07:15 -0300 Subject: [PATCH 3/4] fix block id --- sequencer_core/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index ac4fe72..25e0390 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -73,10 +73,7 @@ impl SequencerCore { sequencer_config: config, }; - loop { - let Ok(block) = this.store.block_store.get_block_at_id(block_id) else { - break; - }; + while let Ok(block) = this.store.block_store.get_block_at_id(block_id) { for encoded_transaction in block.body.transactions { let transaction = NSSATransaction::try_from(&encoded_transaction).unwrap(); let transaction = this.transaction_pre_check(transaction).unwrap(); @@ -87,6 +84,7 @@ impl SequencerCore { .tx_hash_to_block_map .insert(encoded_transaction.hash(), block_id); } + this.chain_height = block_id; block_id += 1; } From 4a23accbde81edce9a3283440ee02c22b7ec48b7 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Tue, 28 Oct 2025 13:01:54 -0300 Subject: [PATCH 4/4] refactor --- .../src/{sequencer_store => }/block_store.rs | 0 sequencer_core/src/lib.rs | 101 ++++++++++-------- sequencer_core/src/sequencer_store/mod.rs | 65 ----------- sequencer_rpc/src/process.rs | 11 +- 4 files changed, 59 insertions(+), 118 deletions(-) rename sequencer_core/src/{sequencer_store => }/block_store.rs (100%) delete mode 100644 sequencer_core/src/sequencer_store/mod.rs diff --git a/sequencer_core/src/sequencer_store/block_store.rs b/sequencer_core/src/block_store.rs similarity index 100% rename from sequencer_core/src/sequencer_store/block_store.rs rename to sequencer_core/src/block_store.rs diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 25e0390..3bf7b7c 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -9,16 +9,16 @@ use common::{ use config::SequencerConfig; use log::warn; use mempool::MemPool; -use sequencer_store::SequecerChainStore; use serde::{Deserialize, Serialize}; -use crate::sequencer_store::block_store::block_to_transactions_map; +use crate::block_store::SequecerBlockStore; pub mod config; -pub mod sequencer_store; +pub mod block_store; pub struct SequencerCore { - pub store: SequecerChainStore, + pub state: nssa::V02State, + pub block_store: SequecerBlockStore, pub mempool: MemPool, pub sequencer_config: SequencerConfig, pub chain_height: u64, @@ -41,6 +41,24 @@ impl std::error::Error for TransactionMalformationError {} impl SequencerCore { pub fn start_from_config(config: SequencerConfig) -> Self { + let hashable_data = HashableBlockData { + block_id: config.genesis_id, + transactions: vec![], + prev_block_hash: [0; 32], + timestamp: 0, + }; + + let signing_key = nssa::PrivateKey::try_new(config.signing_key).unwrap(); + let genesis_block = hashable_data.into_block(&signing_key); + + //Sequencer should panic if unable to open db, + //as fixing this issue may require actions non-native to program scope + let block_store = SequecerBlockStore::open_db_with_genesis( + &config.home.join("rocksdb"), + Some(genesis_block), + signing_key, + ) + .unwrap(); let mut initial_commitments = vec![]; for init_comm_data in config.initial_commitments.clone() { @@ -55,42 +73,46 @@ impl SequencerCore { initial_commitments.push(comm); } - let store = SequecerChainStore::new_with_genesis( - &config.home, - config.genesis_id, - config.is_genesis_random, - &config.initial_accounts, - &initial_commitments, - nssa::PrivateKey::try_new(config.signing_key).unwrap(), - ); + let init_accs: Vec<(nssa::Address, u128)> = config + .initial_accounts + .iter() + .map(|acc_data| (acc_data.addr.parse().unwrap(), acc_data.balance)) + .collect(); - let mut block_id = config.genesis_id; + let mut state = nssa::V02State::new_with_genesis_accounts(&init_accs, &initial_commitments); + + #[cfg(feature = "testnet")] + state.add_pinata_program("cafe".repeat(16).parse().unwrap()); let mut this = Self { - store, + state, + block_store, mempool: MemPool::default(), chain_height: config.genesis_id, sequencer_config: config, }; - while let Ok(block) = this.store.block_store.get_block_at_id(block_id) { - for encoded_transaction in block.body.transactions { - let transaction = NSSATransaction::try_from(&encoded_transaction).unwrap(); - let transaction = this.transaction_pre_check(transaction).unwrap(); - this.execute_check_transaction_on_state(transaction) - .unwrap(); - this.store - .block_store - .tx_hash_to_block_map - .insert(encoded_transaction.hash(), block_id); - } - this.chain_height = block_id; - block_id += 1; - } + this.sync_state_with_stored_blocks(); this } + fn sync_state_with_stored_blocks(&mut self) { + let mut next_block_id = self.sequencer_config.genesis_id + 1; + while let Ok(block) = self.block_store.get_block_at_id(next_block_id) { + for encoded_transaction in block.body.transactions { + let transaction = NSSATransaction::try_from(&encoded_transaction).unwrap(); + self.execute_check_transaction_on_state(transaction) + .unwrap(); + self.block_store + .tx_hash_to_block_map + .insert(encoded_transaction.hash(), next_block_id); + } + self.chain_height = next_block_id; + next_block_id += 1; + } + } + pub fn transaction_pre_check( &mut self, tx: NSSATransaction, @@ -145,20 +167,17 @@ impl SequencerCore { ) -> Result { match &tx { NSSATransaction::Public(tx) => { - self.store - .state + self.state .transition_from_public_transaction(tx) .inspect_err(|err| warn!("Error at transition {err:#?}"))?; } NSSATransaction::PrivacyPreserving(tx) => { - self.store - .state + self.state .transition_from_privacy_preserving_transaction(tx) .inspect_err(|err| warn!("Error at transition {err:#?}"))?; } NSSATransaction::ProgramDeployment(tx) => { - self.store - .state + self.state .transition_from_program_deployment_transaction(tx) .inspect_err(|err| warn!("Error at transition {err:#?}"))?; } @@ -190,7 +209,6 @@ impl SequencerCore { } let prev_block_hash = self - .store .block_store .get_block_at_id(self.chain_height)? .header @@ -205,9 +223,9 @@ impl SequencerCore { timestamp: curr_time, }; - let block = hashable_data.into_block(&self.store.block_store.signing_key); + let block = hashable_data.into_block(&self.block_store.signing_key); - self.store.block_store.put_block_at_id(block)?; + self.block_store.put_block_at_id(block)?; self.chain_height = new_block_height; @@ -311,12 +329,10 @@ mod tests { .unwrap(); let balance_acc_1 = sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc1_addr)) .balance; let balance_acc_2 = sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc2_addr)) .balance; @@ -364,7 +380,6 @@ mod tests { assert_eq!( 10000, sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc1_addr)) .balance @@ -372,7 +387,6 @@ mod tests { assert_eq!( 20000, sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc2_addr)) .balance @@ -517,12 +531,10 @@ mod tests { .unwrap(); let bal_from = sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc1)) .balance; let bal_to = sequencer - .store .state .get_account_by_address(&nssa::Address::new(acc2)) .balance; @@ -615,7 +627,6 @@ mod tests { .produce_new_block_with_mempool_transactions() .unwrap(); let block = sequencer - .store .block_store .get_block_at_id(current_height) .unwrap(); @@ -652,7 +663,6 @@ mod tests { .produce_new_block_with_mempool_transactions() .unwrap(); let block = sequencer - .store .block_store .get_block_at_id(current_height) .unwrap(); @@ -664,7 +674,6 @@ mod tests { .produce_new_block_with_mempool_transactions() .unwrap(); let block = sequencer - .store .block_store .get_block_at_id(current_height) .unwrap(); diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs deleted file mode 100644 index 1081960..0000000 --- a/sequencer_core/src/sequencer_store/mod.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::path::Path; - -use block_store::SequecerBlockStore; -use common::{ - block::HashableBlockData, - transaction::{self, NSSATransaction}, -}; -use nssa::{self, Address}; -use rand::{RngCore, rngs::OsRng}; - -use crate::{config::AccountInitialData, sequencer_store::block_store::block_to_transactions_map}; - -pub mod block_store; - -pub struct SequecerChainStore { - pub state: nssa::V02State, - pub block_store: SequecerBlockStore, -} - -impl SequecerChainStore { - pub fn new_with_genesis( - home_dir: &Path, - genesis_id: u64, - is_genesis_random: bool, - initial_accounts: &[AccountInitialData], - initial_commitments: &[nssa_core::Commitment], - signing_key: nssa::PrivateKey, - ) -> Self { - let init_accs: Vec<(Address, u128)> = initial_accounts - .iter() - .map(|acc_data| (acc_data.addr.parse().unwrap(), acc_data.balance)) - .collect(); - - #[cfg(not(feature = "testnet"))] - let state = nssa::V02State::new_with_genesis_accounts(&init_accs, initial_commitments); - - #[cfg(feature = "testnet")] - let state = { - let mut this = - nssa::V02State::new_with_genesis_accounts(&init_accs, initial_commitments); - this.add_pinata_program("cafe".repeat(16).parse().unwrap()); - this - }; - - let hashable_data = HashableBlockData { - block_id: genesis_id, - transactions: vec![], - prev_block_hash: [0; 32], - timestamp: 0, - }; - - let genesis_block = hashable_data.into_block(&signing_key); - - //Sequencer should panic if unable to open db, - //as fixing this issue may require actions non-native to program scope - let block_store = SequecerBlockStore::open_db_with_genesis( - &home_dir.join("rocksdb"), - Some(genesis_block), - signing_key, - ) - .unwrap(); - - Self { state, block_store } - } -} diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index f8c583f..5e03f58 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -104,7 +104,6 @@ impl JsonHandler { let state = self.sequencer_state.lock().await; state - .store .block_store .get_block_at_id(get_block_req.block_id)? }; @@ -122,7 +121,7 @@ impl JsonHandler { let genesis_id = { let state = self.sequencer_state.lock().await; - state.store.block_store.genesis_id + state.block_store.genesis_id }; let helperstruct = GetGenesisIdResponse { genesis_id }; @@ -173,7 +172,7 @@ impl JsonHandler { let balance = { let state = self.sequencer_state.lock().await; - let account = state.store.state.get_account_by_address(&address); + let account = state.state.get_account_by_address(&address); account.balance }; @@ -200,7 +199,7 @@ impl JsonHandler { addresses .into_iter() - .map(|addr| state.store.state.get_account_by_address(&addr).nonce) + .map(|addr| state.state.get_account_by_address(&addr).nonce) .collect() }; @@ -222,7 +221,7 @@ impl JsonHandler { let account = { let state = self.sequencer_state.lock().await; - state.store.state.get_account_by_address(&address) + state.state.get_account_by_address(&address) }; let helperstruct = GetAccountResponse { account }; @@ -243,7 +242,6 @@ impl JsonHandler { let transaction = { let state = self.sequencer_state.lock().await; state - .store .block_store .get_transaction_by_hash(hash) .map(|tx| borsh::to_vec(&tx).unwrap()) @@ -262,7 +260,6 @@ impl JsonHandler { let membership_proof = { let state = self.sequencer_state.lock().await; state - .store .state .get_proof_for_commitment(&get_proof_req.commitment) };