From f1f8f140493cb4c445f17f7d0d3e276f52bb121b Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:04:24 +0100 Subject: [PATCH 1/6] Split up LedgerDB by Ops type --- bin/citrea/src/rollup/mod.rs | 1 + crates/fullnode/src/lib.rs | 2 + crates/fullnode/src/runner.rs | 14 +- crates/prover/src/lib.rs | 2 + crates/prover/src/runner.rs | 14 +- crates/sequencer/src/commitment_controller.rs | 4 +- crates/sequencer/src/lib.rs | 2 + crates/sequencer/src/sequencer.rs | 13 +- .../full-node/db/sov-db/src/ledger_db/mod.rs | 641 +++++++++--------- .../full-node/db/sov-db/src/ledger_db/rpc.rs | 4 +- .../db/sov-db/src/ledger_db/traits.rs | 216 ++++++ 11 files changed, 570 insertions(+), 343 deletions(-) create mode 100644 crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs diff --git a/bin/citrea/src/rollup/mod.rs b/bin/citrea/src/rollup/mod.rs index 83238e722..71783f522 100644 --- a/bin/citrea/src/rollup/mod.rs +++ b/bin/citrea/src/rollup/mod.rs @@ -4,6 +4,7 @@ use citrea_fullnode::{CitreaFullnode, FullNode}; use citrea_prover::{CitreaProver, Prover}; use citrea_sequencer::{CitreaSequencer, Sequencer, SequencerConfig}; pub use mock::*; +use sov_db::ledger_db::SharedLedgerOps; use sov_modules_api::storage::HierarchicalStorageManager; use sov_modules_api::Spec; use sov_modules_rollup_blueprint::RollupBlueprint; diff --git a/crates/fullnode/src/lib.rs b/crates/fullnode/src/lib.rs index 7af6b108e..bfbbe26b5 100644 --- a/crates/fullnode/src/lib.rs +++ b/crates/fullnode/src/lib.rs @@ -1,6 +1,7 @@ use std::net::SocketAddr; pub use runner::*; +use sov_db::ledger_db::LedgerDB; use sov_modules_rollup_blueprint::RollupBlueprint; use sov_modules_stf_blueprint::StfBlueprint; use tokio::sync::oneshot; @@ -18,6 +19,7 @@ pub struct FullNode { S::DaService, S::Vm, S::NativeContext, + LedgerDB, >, /// Rpc methods for the rollup. pub rpc_methods: jsonrpsee::RpcModule<()>, diff --git a/crates/fullnode/src/runner.rs b/crates/fullnode/src/runner.rs index 38c9d9d22..786033675 100644 --- a/crates/fullnode/src/runner.rs +++ b/crates/fullnode/src/runner.rs @@ -14,7 +14,8 @@ use jsonrpsee::RpcModule; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; use sequencer_client::{GetSoftBatchResponse, SequencerClient}; -use sov_db::ledger_db::{LedgerDB, SlotCommit}; +use sov_db::ledger_db::NodeLedgerOps; +use sov_db::ledger_db::SlotCommit; use sov_db::schema::types::{BatchNumber, SlotNumber, StoredSoftBatch, StoredStateTransition}; use sov_modules_api::Context; use sov_modules_stf_blueprint::StfBlueprintTrait; @@ -36,7 +37,7 @@ use tracing::{debug, error, info, instrument, warn}; type StateRoot = >::StateRoot; /// Citrea's own STF runner implementation. -pub struct CitreaFullnode +pub struct CitreaFullnode where Da: DaService, Vm: ZkvmHost + Zkvm, @@ -44,14 +45,14 @@ where Stf: StateTransitionFunction::ValidityCondition> + StfBlueprintTrait, C: Context, + DB: NodeLedgerOps, { start_l2_height: u64, start_l1_height: u64, da_service: Da, stf: Stf, storage_manager: Sm, - /// made pub so that sequencer can clone it - pub ledger_db: LedgerDB, + ledger_db: DB, state_root: StateRoot, batch_hash: SoftConfirmationHash, rpc_config: RpcConfig, @@ -67,7 +68,7 @@ where sync_blocks_count: u64, } -impl CitreaFullnode +impl CitreaFullnode where Da: DaService + Clone + Send + Sync + 'static, Vm: ZkvmHost + Zkvm, @@ -80,6 +81,7 @@ where ChangeSet = Sm::NativeChangeSet, > + StfBlueprintTrait, C: Context, + DB: NodeLedgerOps, { /// Creates a new `StateTransitionRunner`. /// @@ -92,7 +94,7 @@ where public_keys: RollupPublicKeys, rpc_config: RpcConfig, da_service: Da, - ledger_db: LedgerDB, + ledger_db: DB, stf: Stf, mut storage_manager: Sm, init_variant: InitVariant, diff --git a/crates/prover/src/lib.rs b/crates/prover/src/lib.rs index ebc730ece..3f334fb09 100644 --- a/crates/prover/src/lib.rs +++ b/crates/prover/src/lib.rs @@ -1,5 +1,6 @@ use std::net::SocketAddr; +use sov_db::ledger_db::LedgerDB; use sov_modules_rollup_blueprint::RollupBlueprint; use sov_modules_stf_blueprint::StfBlueprint; use tokio::sync::oneshot; @@ -20,6 +21,7 @@ pub struct Prover { S::Vm, StfBlueprint, S::ProverService, + LedgerDB, >, /// Rpc methods for the rollup. pub rpc_methods: jsonrpsee::RpcModule<()>, diff --git a/crates/prover/src/runner.rs b/crates/prover/src/runner.rs index d9b516eae..9d5339cb4 100644 --- a/crates/prover/src/runner.rs +++ b/crates/prover/src/runner.rs @@ -16,7 +16,8 @@ use jsonrpsee::RpcModule; use rand::Rng; use sequencer_client::{GetSoftBatchResponse, SequencerClient}; use shared_backup_db::{DbPoolError, PostgresConnector, ProofType}; -use sov_db::ledger_db::{LedgerDB, SlotCommit}; +use sov_db::ledger_db::ProverLedgerOps; +use sov_db::ledger_db::SlotCommit; use sov_db::schema::types::{BatchNumber, SlotNumber, StoredStateTransition}; use sov_modules_api::storage::HierarchicalStorageManager; use sov_modules_api::{BlobReaderTrait, Context, SignedSoftConfirmationBatch, SlotData}; @@ -42,7 +43,7 @@ type CommitmentStateTransitionData = ( VecDeque::Spec as DaSpec>::BlockHeader>>, ); -pub struct CitreaProver +pub struct CitreaProver where C: Context, Da: DaService, @@ -52,13 +53,13 @@ where + StfBlueprintTrait, Ps: ProverService, + DB: ProverLedgerOps + Clone, { start_l2_height: u64, da_service: Da, stf: Stf, storage_manager: Sm, - /// made pub so that sequencer can clone it - pub ledger_db: LedgerDB, + ledger_db: DB, state_root: StateRoot, batch_hash: SoftConfirmationHash, rpc_config: RpcConfig, @@ -74,7 +75,7 @@ where sync_blocks_count: u64, } -impl CitreaProver +impl CitreaProver where C: Context, Da: DaService + Clone + Send + Sync + 'static, @@ -88,6 +89,7 @@ where ChangeSet = Sm::NativeChangeSet, > + StfBlueprintTrait, Ps: ProverService, + DB: ProverLedgerOps + Clone, { /// Creates a new `StateTransitionRunner`. /// @@ -100,7 +102,7 @@ where public_keys: RollupPublicKeys, rpc_config: RpcConfig, da_service: Da, - ledger_db: LedgerDB, + ledger_db: DB, stf: Stf, mut storage_manager: Sm, init_variant: InitVariant, diff --git a/crates/sequencer/src/commitment_controller.rs b/crates/sequencer/src/commitment_controller.rs index 8548cfae7..03782baa4 100644 --- a/crates/sequencer/src/commitment_controller.rs +++ b/crates/sequencer/src/commitment_controller.rs @@ -4,7 +4,7 @@ use std::ops::RangeInclusive; use anyhow::anyhow; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; -use sov_db::ledger_db::LedgerDB; +use sov_db::ledger_db::SequencerLedgerOps; use sov_db::schema::types::BatchNumber; use sov_rollup_interface::da::SequencerCommitment; use tracing::{debug, instrument}; @@ -20,7 +20,7 @@ pub struct CommitmentInfo { /// Returns `CommitmentInfo` if the sequencer should commit #[instrument(level = "debug", skip_all, fields(prev_l1_height), err)] pub fn get_commitment_info( - ledger_db: &LedgerDB, + ledger_db: &impl SequencerLedgerOps, min_soft_confirmations_per_commitment: u64, state_diff_threshold_reached: bool, ) -> anyhow::Result> { diff --git a/crates/sequencer/src/lib.rs b/crates/sequencer/src/lib.rs index 2957b2261..8c8940595 100644 --- a/crates/sequencer/src/lib.rs +++ b/crates/sequencer/src/lib.rs @@ -11,6 +11,7 @@ use std::net::SocketAddr; pub use config::{SequencerConfig, SequencerMempoolConfig}; pub use sequencer::CitreaSequencer; +use sov_db::ledger_db::LedgerDB; use sov_modules_rollup_blueprint::RollupBlueprint; use sov_modules_stf_blueprint::StfBlueprint; use tokio::sync::oneshot; @@ -26,6 +27,7 @@ pub struct Sequencer { S::StorageManager, S::Vm, StfBlueprint, + LedgerDB, >, /// Rpc methods for the rollup. pub rpc_methods: jsonrpsee::RpcModule<()>, diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index 79bdff3bf..b491c22fb 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -27,7 +27,8 @@ use shared_backup_db::{CommitmentStatus, PostgresConnector}; use soft_confirmation_rule_enforcer::SoftConfirmationRuleEnforcer; use sov_accounts::Accounts; use sov_accounts::Response::{AccountEmpty, AccountExists}; -use sov_db::ledger_db::{LedgerDB, SlotCommit}; +use sov_db::ledger_db::SequencerLedgerOps; +use sov_db::ledger_db::SlotCommit; use sov_db::schema::types::{BatchNumber, SlotNumber}; use sov_modules_api::hooks::HookSoftConfirmationInfo; use sov_modules_api::transaction::Transaction; @@ -64,7 +65,7 @@ type StateRoot = >::StateRoot; /// Contains previous height, latest finalized block and fee rate. type L1Data = (::FilteredBlock, u128); -pub struct CitreaSequencer +pub struct CitreaSequencer where C: Context, Da: DaService, @@ -72,6 +73,7 @@ where Vm: ZkvmHost, Stf: StateTransitionFunction::ValidityCondition> + StfBlueprintTrait, + DB: SequencerLedgerOps + Send + Clone + 'static, { da_service: Da, mempool: Arc>, @@ -80,7 +82,7 @@ where l2_force_block_rx: UnboundedReceiver<()>, db_provider: DbProvider, storage: C::Storage, - ledger_db: LedgerDB, + ledger_db: DB, config: SequencerConfig, stf: Stf, deposit_mempool: Arc>, @@ -98,7 +100,7 @@ enum L2BlockMode { NotEmpty, } -impl CitreaSequencer +impl CitreaSequencer where C: Context, Da: DaService + Clone, @@ -111,6 +113,7 @@ where PreState = Sm::NativeStorage, ChangeSet = Sm::NativeChangeSet, > + StfBlueprintTrait, + DB: SequencerLedgerOps + Send + Clone + 'static, { #[allow(clippy::too_many_arguments)] pub fn new( @@ -121,7 +124,7 @@ where mut storage_manager: Sm, init_variant: InitVariant, public_keys: RollupPublicKeys, - ledger_db: LedgerDB, + ledger_db: DB, rpc_config: RpcConfig, ) -> anyhow::Result { let (l2_force_block_tx, l2_force_block_rx) = unbounded(); diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs index 85f45324d..d0d7bc6be 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs @@ -25,6 +25,9 @@ use crate::schema::types::{ }; mod rpc; +mod traits; + +pub use traits::*; const LEDGER_DB_PATH_SUFFIX: &str = "ledger"; @@ -127,69 +130,6 @@ impl LedgerDB { }) } - /// Get the next slot, block, transaction, and event numbers - #[instrument(level = "trace", skip(self), ret)] - pub fn get_next_items_numbers(&self) -> ItemNumbers { - self.next_item_numbers.lock().unwrap().clone() - } - - /// Gets all slots with numbers `range.start` to `range.end`. If `range.end` is outside - /// the range of the database, the result will smaller than the requested range. - /// Note that this method blindly preallocates for the requested range, so it should not be exposed - /// directly via rpc. - #[instrument(level = "trace", skip(self), err)] - pub(crate) fn _get_slot_range( - &self, - range: &std::ops::Range, - ) -> Result, anyhow::Error> { - self.get_data_range::(range) - } - - /// Gets all batches with numbers `range.start` to `range.end`. If `range.end` is outside - /// the range of the database, the result will smaller than the requested range. - /// Note that this method blindly preallocates for the requested range, so it should not be exposed - /// directly via rpc. - #[instrument(level = "trace", skip(self), err)] - pub(crate) fn get_batch_range( - &self, - range: &std::ops::Range, - ) -> Result, anyhow::Error> { - self.get_data_range::(range) - } - - /// Gets all soft confirmations by numbers - #[instrument(level = "trace", skip(self), err)] - pub fn get_soft_batch_by_number( - &self, - number: &BatchNumber, - ) -> Result, anyhow::Error> { - self.db.get::(number) - } - - /// Gets all soft confirmations with numbers `range.start` to `range.end`. If `range.end` is outside - /// the range of the database, the result will smaller than the requested range. - /// Note that this method blindly preallocates for the requested range, so it should not be exposed - /// directly via rpc. - #[instrument(level = "trace", skip(self), err)] - pub fn get_soft_batch_range( - &self, - range: &std::ops::Range, - ) -> Result, anyhow::Error> { - self.get_data_range::(range) - } - - /// Gets all transactions with numbers `range.start` to `range.end`. If `range.end` is outside - /// the range of the database, the result will smaller than the requested range. - /// Note that this method blindly preallocates for the requested range, so it should not be exposed - /// directly via rpc. - #[instrument(level = "trace", skip(self), err)] - pub(crate) fn get_tx_range( - &self, - range: &std::ops::Range, - ) -> Result, anyhow::Error> { - self.get_data_range::(range) - } - /// Gets all data with identifier in `range.start` to `range.end`. If `range.end` is outside /// the range of the database, the result will smaller than the requested range. /// Note that this method blindly preallocates for the requested range, so it should not be exposed @@ -212,17 +152,22 @@ impl LedgerDB { Ok(out) } - #[instrument(level = "trace", skip(self, schema_batch), err, ret)] - fn put_slot( - &self, - slot: &StoredSlot, - slot_number: &SlotNumber, - schema_batch: &mut SchemaBatch, - ) -> Result<(), anyhow::Error> { - schema_batch.put::(slot_number, slot)?; - schema_batch.put::(&slot.hash, slot_number) + fn last_version_written, U: Into>( + db: &DB, + _schema: T, + ) -> anyhow::Result> { + let mut iter = db.iter::()?; + iter.seek_to_last(); + + match iter.next() { + Some(Ok(item)) => Ok(Some(item.key.into())), + Some(Err(e)) => Err(e), + _ => Ok(None), + } } +} +impl SharedLedgerOps for LedgerDB { #[instrument(level = "trace", skip(self, schema_batch), err, ret)] fn put_soft_batch( &self, @@ -269,7 +214,7 @@ impl LedgerDB { } /// Commits a soft batch to the database by inserting its transactions and batches before - pub fn commit_soft_batch( + fn commit_soft_batch( &self, batch_receipt: SoftBatchReceipt, include_tx_body: bool, @@ -356,93 +301,9 @@ impl LedgerDB { Ok(()) } - /// Commits a slot to the database by inserting its events, transactions, and batches before - /// inserting the slot metadata. - #[instrument(level = "trace", skip_all, err, ret)] - pub fn commit_slot( - &self, - data_to_commit: SlotCommit, - ) -> Result<(), anyhow::Error> { - // Create a scope to ensure that the lock is released before we commit to the db - let mut current_item_numbers = { - let mut next_item_numbers = self.next_item_numbers.lock().unwrap(); - let item_numbers = next_item_numbers.clone(); - next_item_numbers.slot_number += 1; - next_item_numbers.batch_number += data_to_commit.batch_receipts.len() as u64; - next_item_numbers.tx_number += data_to_commit.num_txs as u64; - next_item_numbers.event_number += data_to_commit.num_events as u64; - item_numbers - // The lock is released here - }; - - let mut schema_batch = SchemaBatch::new(); - - let first_batch_number = current_item_numbers.batch_number; - let last_batch_number = first_batch_number + data_to_commit.batch_receipts.len() as u64; - // Insert data from "bottom up" to ensure consistency if the application crashes during insertion - for batch_receipt in data_to_commit.batch_receipts.into_iter() { - let first_tx_number = current_item_numbers.tx_number; - let last_tx_number = first_tx_number + batch_receipt.tx_receipts.len() as u64; - // Insert transactions and events from each batch before inserting the batch - for tx in batch_receipt.tx_receipts.into_iter() { - let (tx_to_store, events) = - split_tx_for_storage(tx, current_item_numbers.event_number); - for event in events.into_iter() { - self.put_event( - &event, - &EventNumber(current_item_numbers.event_number), - TxNumber(current_item_numbers.tx_number), - &mut schema_batch, - )?; - current_item_numbers.event_number += 1; - } - self.put_transaction( - &tx_to_store, - &TxNumber(current_item_numbers.tx_number), - &mut schema_batch, - )?; - current_item_numbers.tx_number += 1; - } - - // Insert batch - let batch_to_store = StoredBatch { - hash: batch_receipt.hash, - txs: TxNumber(first_tx_number)..TxNumber(last_tx_number), - }; - self.put_batch( - &batch_to_store, - &BatchNumber(current_item_numbers.batch_number), - &mut schema_batch, - )?; - current_item_numbers.batch_number += 1; - } - - // Once all batches are inserted, Insert slot - let slot_to_store = StoredSlot { - hash: data_to_commit.slot_data.hash(), - // TODO: Add a method to the slot data trait allowing additional data to be stored - extra_data: vec![].into(), - batches: BatchNumber(first_batch_number)..BatchNumber(last_batch_number), - }; - self.put_slot( - &slot_to_store, - &SlotNumber(current_item_numbers.slot_number), - &mut schema_batch, - )?; - - self.db.write_schemas(schema_batch)?; - - // Notify subscribers. This call returns an error IFF there are no subscribers, so we don't need to check the result - let _ = self - .slot_subscriptions - .send(current_item_numbers.slot_number); - - Ok(()) - } - /// Records the L2 height that was created as a soft confirmaiton of an L1 height #[instrument(level = "trace", skip(self), err, ret)] - pub fn extend_l2_range_of_l1_slot( + fn extend_l2_range_of_l1_slot( &self, l1_height: SlotNumber, l2_height: BatchNumber, @@ -464,25 +325,53 @@ impl LedgerDB { Ok(()) } - /// Used by the sequencer to record that it has committed to soft confirmations on a given L2 height - #[instrument(level = "trace", skip(self), err, ret)] - pub fn set_last_sequencer_commitment_l2_height( + /// Get the next slot, block, transaction, and event numbers + #[instrument(level = "trace", skip(self), ret)] + fn get_next_items_numbers(&self) -> ItemNumbers { + self.next_item_numbers.lock().unwrap().clone() + } + + /// Gets all slots with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + #[instrument(level = "trace", skip(self), err)] + fn _get_slot_range( &self, - l2_height: BatchNumber, - ) -> Result<(), anyhow::Error> { - let mut schema_batch = SchemaBatch::new(); + range: &std::ops::Range, + ) -> Result, anyhow::Error> { + self.get_data_range::(range) + } - schema_batch - .put::(&(), &l2_height) - .unwrap(); - self.db.write_schemas(schema_batch)?; + /// Gets all batches with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + #[instrument(level = "trace", skip(self), err)] + fn get_batch_range( + &self, + range: &std::ops::Range, + ) -> Result, anyhow::Error> { + self.get_data_range::(range) + } - Ok(()) + /// Gets l1 height of l1 hash + #[instrument(level = "trace", skip(self), err, ret)] + fn get_state_diff(&self) -> Result { + self.db + .get::(&()) + .map(|diff| diff.unwrap_or_default()) + } + + /// Sets l1 height of l1 hash + #[instrument(level = "trace", skip(self), err, ret)] + fn set_l1_height_of_l1_hash(&self, hash: [u8; 32], height: u64) -> anyhow::Result<()> { + self.db.put::(&hash, &SlotNumber(height)) } /// Saves a soft confirmation status for a given L1 height #[instrument(level = "trace", skip(self), err, ret)] - pub fn put_soft_confirmation_status( + fn put_soft_confirmation_status( &self, height: BatchNumber, status: sov_rollup_interface::rpc::SoftConfirmationStatus, @@ -497,36 +386,49 @@ impl LedgerDB { Ok(()) } - fn last_version_written, U: Into>( - db: &DB, - _schema: T, - ) -> anyhow::Result> { - let mut iter = db.iter::()?; - iter.seek_to_last(); + /// Gets the commitments in the da slot with given height if any + /// Adds the new coming commitment info + #[instrument(level = "trace", skip(self, commitment), err, ret)] + fn update_commitments_on_da_slot( + &self, + height: u64, + commitment: SequencerCommitment, + ) -> anyhow::Result<()> { + // get commitments + let commitments = self.db.get::(&SlotNumber(height))?; - match iter.next() { - Some(Ok(item)) => Ok(Some(item.key.into())), - Some(Err(e)) => Err(e), - _ => Ok(None), + match commitments { + // If there were other commitments, upsert + Some(mut commitments) => { + commitments.push(commitment); + self.db + .put::(&SlotNumber(height), &commitments) + } + // Else insert + None => self + .db + .put::(&SlotNumber(height), &vec![commitment]), } } - /// Get the most recent committed slot, if any - #[instrument(level = "trace", skip(self), err)] - pub fn get_head_slot(&self) -> anyhow::Result> { - let mut iter = self.db.iter::()?; - iter.seek_to_last(); + /// Set the genesis state root + #[instrument(level = "trace", skip_all, err, ret)] + fn set_l2_genesis_state_root( + &self, + state_root: &StateRoot, + ) -> anyhow::Result<()> { + let buf = bincode::serialize(state_root)?; + let mut schema_batch = SchemaBatch::new(); + schema_batch.put::(&(), &buf)?; - match iter.next() { - Some(Ok(item)) => Ok(Some(item.into_tuple())), - Some(Err(e)) => Err(e), - _ => Ok(None), - } + self.db.write_schemas(schema_batch)?; + + Ok(()) } /// Get the most recent committed soft batch, if any #[instrument(level = "trace", skip(self), err)] - pub fn get_head_soft_batch(&self) -> anyhow::Result> { + fn get_head_soft_batch(&self) -> anyhow::Result> { let mut iter = self.db.iter::()?; iter.seek_to_last(); @@ -537,66 +439,58 @@ impl LedgerDB { } } - /// Gets all pending commitments' l2 ranges. - /// Returns start-end L2 heights. - #[instrument(level = "trace", skip(self), err)] - pub fn get_pending_commitments_l2_range(&self) -> anyhow::Result> { - let mut iter = self.db.iter::()?; - iter.seek_to_first(); - - let mut l2_ranges = iter - .map(|item| item.map(|item| item.key)) - .collect::, _>>()?; - // Sort ascending - l2_ranges.sort(); - - Ok(l2_ranges) - } - - /// Put a pending commitment l2 range + /// Gets all soft confirmations with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. #[instrument(level = "trace", skip(self), err)] - pub fn put_pending_commitment_l2_range(&self, l2_range: &L2HeightRange) -> anyhow::Result<()> { - self.db - .put::(l2_range, &()) + fn get_soft_batch_range( + &self, + range: &std::ops::Range, + ) -> Result, anyhow::Error> { + self.get_data_range::(range) } - /// Delete a pending commitment l2 range + /// Gets all soft confirmations by numbers #[instrument(level = "trace", skip(self), err)] - pub fn delete_pending_commitment_l2_range( + fn get_soft_batch_by_number( &self, - l2_range: &L2HeightRange, - ) -> anyhow::Result<()> { - self.db - .delete::(l2_range) - } - - /// Get the most recent committed batch - /// Returns L2 height. - #[instrument(level = "trace", skip(self), err, ret)] - pub fn get_last_sequencer_commitment_l2_height(&self) -> anyhow::Result> { - self.db.get::(&()) + number: &BatchNumber, + ) -> Result, anyhow::Error> { + self.db.get::(number) } +} - /// Get L2 height range for a given L1 height. - /// This means L2 heights in that range were soft confirmations for L1 height. - #[instrument(level = "trace", skip(self), err, ret)] - pub fn get_l2_range_by_l1_height( +impl ProverLedgerOps for LedgerDB { + /// Get the state root by L2 height + #[instrument(level = "trace", skip_all, err)] + fn get_l2_state_root( &self, - l1_height: SlotNumber, - ) -> anyhow::Result> { - self.db.get::(&l1_height) + l2_height: u64, + ) -> anyhow::Result> { + if l2_height == 0 { + self.db + .get::(&())? + .map(|state_root| bincode::deserialize(&state_root).map_err(Into::into)) + .transpose() + } else { + self.db + .get::(&BatchNumber(l2_height))? + .map(|soft_batch| bincode::deserialize(&soft_batch.state_root).map_err(Into::into)) + .transpose() + } } /// Get the last scanned slot by the prover #[instrument(level = "trace", skip(self), err, ret)] - pub fn get_prover_last_scanned_l1_height(&self) -> anyhow::Result> { + fn get_prover_last_scanned_l1_height(&self) -> anyhow::Result> { self.db.get::(&()) } /// Set the last scanned slot by the prover /// Called by the prover. #[instrument(level = "trace", skip(self), err, ret)] - pub fn set_prover_last_scanned_l1_height(&self, l1_height: SlotNumber) -> anyhow::Result<()> { + fn set_prover_last_scanned_l1_height(&self, l1_height: SlotNumber) -> anyhow::Result<()> { let mut schema_batch = SchemaBatch::new(); schema_batch @@ -609,7 +503,7 @@ impl LedgerDB { /// Get the witness by L2 height #[instrument(level = "trace", skip_all, err)] - pub fn get_l2_witness( + fn get_l2_witness( &self, l2_height: u64, ) -> anyhow::Result> { @@ -622,9 +516,27 @@ impl LedgerDB { } } + /// Stores proof related data on disk, accessible via l1 slot height + #[instrument(level = "trace", skip(self, proof, state_transition), err, ret)] + fn put_proof_data( + &self, + l1_height: u64, + l1_tx_id: [u8; 32], + proof: Proof, + state_transition: StoredStateTransition, + ) -> anyhow::Result<()> { + let data_to_store = StoredProof { + l1_tx_id, + proof, + state_transition, + }; + self.db + .put::(&SlotNumber(l1_height), &data_to_store) + } + /// Set the witness by L2 height #[instrument(level = "trace", skip_all, err, ret)] - pub fn set_l2_witness( + fn set_l2_witness( &self, l2_height: u64, witness: &Witness, @@ -637,96 +549,172 @@ impl LedgerDB { Ok(()) } +} - /// Set the genesis state root +impl SequencerLedgerOps for LedgerDB { + /// Put slots + #[instrument(level = "trace", skip(self, schema_batch), err, ret)] + fn put_slot( + &self, + slot: &StoredSlot, + slot_number: &SlotNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<(), anyhow::Error> { + schema_batch.put::(slot_number, slot)?; + schema_batch.put::(&slot.hash, slot_number) + } + + /// Commits a slot to the database by inserting its events, transactions, and batches before + /// inserting the slot metadata. #[instrument(level = "trace", skip_all, err, ret)] - pub fn set_l2_genesis_state_root( + fn commit_slot( &self, - state_root: &StateRoot, - ) -> anyhow::Result<()> { - let buf = bincode::serialize(state_root)?; + data_to_commit: SlotCommit, + ) -> Result<(), anyhow::Error> { + // Create a scope to ensure that the lock is released before we commit to the db + let mut current_item_numbers = { + let mut next_item_numbers = self.next_item_numbers.lock().unwrap(); + let item_numbers = next_item_numbers.clone(); + next_item_numbers.slot_number += 1; + next_item_numbers.batch_number += data_to_commit.batch_receipts.len() as u64; + next_item_numbers.tx_number += data_to_commit.num_txs as u64; + next_item_numbers.event_number += data_to_commit.num_events as u64; + item_numbers + // The lock is released here + }; + let mut schema_batch = SchemaBatch::new(); - schema_batch.put::(&(), &buf)?; + + let first_batch_number = current_item_numbers.batch_number; + let last_batch_number = first_batch_number + data_to_commit.batch_receipts.len() as u64; + // Insert data from "bottom up" to ensure consistency if the application crashes during insertion + for batch_receipt in data_to_commit.batch_receipts.into_iter() { + let first_tx_number = current_item_numbers.tx_number; + let last_tx_number = first_tx_number + batch_receipt.tx_receipts.len() as u64; + // Insert transactions and events from each batch before inserting the batch + for tx in batch_receipt.tx_receipts.into_iter() { + let (tx_to_store, events) = + split_tx_for_storage(tx, current_item_numbers.event_number); + for event in events.into_iter() { + self.put_event( + &event, + &EventNumber(current_item_numbers.event_number), + TxNumber(current_item_numbers.tx_number), + &mut schema_batch, + )?; + current_item_numbers.event_number += 1; + } + self.put_transaction( + &tx_to_store, + &TxNumber(current_item_numbers.tx_number), + &mut schema_batch, + )?; + current_item_numbers.tx_number += 1; + } + + // Insert batch + let batch_to_store = StoredBatch { + hash: batch_receipt.hash, + txs: TxNumber(first_tx_number)..TxNumber(last_tx_number), + }; + self.put_batch( + &batch_to_store, + &BatchNumber(current_item_numbers.batch_number), + &mut schema_batch, + )?; + current_item_numbers.batch_number += 1; + } + + // Once all batches are inserted, Insert slot + let slot_to_store = StoredSlot { + hash: data_to_commit.slot_data.hash(), + // TODO: Add a method to the slot data trait allowing additional data to be stored + extra_data: vec![].into(), + batches: BatchNumber(first_batch_number)..BatchNumber(last_batch_number), + }; + self.put_slot( + &slot_to_store, + &SlotNumber(current_item_numbers.slot_number), + &mut schema_batch, + )?; self.db.write_schemas(schema_batch)?; + // Notify subscribers. This call returns an error IFF there are no subscribers, so we don't need to check the result + let _ = self + .slot_subscriptions + .send(current_item_numbers.slot_number); + Ok(()) } - /// Get the state root by L2 height - #[instrument(level = "trace", skip_all, err)] - pub fn get_l2_state_root( + /// Used by the sequencer to record that it has committed to soft confirmations on a given L2 height + #[instrument(level = "trace", skip(self), err, ret)] + fn set_last_sequencer_commitment_l2_height( &self, - l2_height: u64, - ) -> anyhow::Result> { - if l2_height == 0 { - self.db - .get::(&())? - .map(|state_root| bincode::deserialize(&state_root).map_err(Into::into)) - .transpose() - } else { - self.db - .get::(&BatchNumber(l2_height))? - .map(|soft_batch| bincode::deserialize(&soft_batch.state_root).map_err(Into::into)) - .transpose() - } + l2_height: BatchNumber, + ) -> Result<(), anyhow::Error> { + let mut schema_batch = SchemaBatch::new(); + + schema_batch.put::(&(), &l2_height)?; + self.db.write_schemas(schema_batch)?; + + Ok(()) } - /// Gets the commitments in the da slot with given height if any - /// Adds the new coming commitment info - #[instrument(level = "trace", skip(self, commitment), err, ret)] - pub fn update_commitments_on_da_slot( - &self, - height: u64, - commitment: SequencerCommitment, - ) -> anyhow::Result<()> { - // get commitments - let commitments = self.db.get::(&SlotNumber(height))?; + /// Gets all pending commitments' l2 ranges. + /// Returns start-end L2 heights. + #[instrument(level = "trace", skip(self), err)] + fn get_pending_commitments_l2_range(&self) -> anyhow::Result> { + let mut iter = self.db.iter::()?; + iter.seek_to_first(); - match commitments { - // If there were other commitments, upsert - Some(mut commitments) => { - commitments.push(commitment); - self.db - .put::(&SlotNumber(height), &commitments) - } - // Else insert - None => self - .db - .put::(&SlotNumber(height), &vec![commitment]), - } + let mut l2_ranges = iter + .map(|item| item.map(|item| item.key)) + .collect::, _>>()?; + // Sort ascending + l2_ranges.sort(); + + Ok(l2_ranges) } - /// Gets the commitments in the da slot with given height if any + /// Put a pending commitment l2 range #[instrument(level = "trace", skip(self), err)] - pub fn get_commitments_on_da_slot( - &self, - height: u64, - ) -> anyhow::Result>> { - self.db.get::(&SlotNumber(height)) + fn put_pending_commitment_l2_range(&self, l2_range: &L2HeightRange) -> anyhow::Result<()> { + self.db + .put::(l2_range, &()) } - /// Stores proof related data on disk, accessible via l1 slot height - #[instrument(level = "trace", skip(self, proof, state_transition), err, ret)] - pub fn put_proof_data( - &self, - l1_height: u64, - l1_tx_id: [u8; 32], - proof: Proof, - state_transition: StoredStateTransition, - ) -> anyhow::Result<()> { - let data_to_store = StoredProof { - l1_tx_id, - proof, - state_transition, - }; + /// Delete a pending commitment l2 range + #[instrument(level = "trace", skip(self), err)] + fn delete_pending_commitment_l2_range(&self, l2_range: &L2HeightRange) -> anyhow::Result<()> { self.db - .put::(&SlotNumber(l1_height), &data_to_store) + .delete::(l2_range) } + /// Sets the latest state diff + #[instrument(level = "trace", skip(self), err, ret)] + fn set_state_diff(&self, state_diff: StateDiff) -> anyhow::Result<()> { + let mut schema_batch = SchemaBatch::new(); + schema_batch.put::(&(), &state_diff)?; + + self.db.write_schemas(schema_batch)?; + + Ok(()) + } + + /// Get the most recent committed batch + /// Returns L2 height. + #[instrument(level = "trace", skip(self), err, ret)] + fn get_last_sequencer_commitment_l2_height(&self) -> anyhow::Result> { + self.db.get::(&()) + } +} + +impl NodeLedgerOps for LedgerDB { /// Stores proof related data on disk, accessible via l1 slot height #[instrument(level = "trace", skip(self, proof, state_transition), err, ret)] - pub fn update_verified_proof_data( + fn update_verified_proof_data( &self, l1_height: u64, proof: Proof, @@ -756,34 +744,43 @@ impl LedgerDB { } } - /// Sets l1 height of l1 hash - #[instrument(level = "trace", skip(self), err, ret)] - pub fn set_l1_height_of_l1_hash(&self, hash: [u8; 32], height: u64) -> anyhow::Result<()> { - self.db.put::(&hash, &SlotNumber(height)) - } + /// Get the most recent committed slot, if any + #[instrument(level = "trace", skip(self), err)] + fn get_head_slot(&self) -> anyhow::Result> { + let mut iter = self.db.iter::()?; + iter.seek_to_last(); - /// Gets l1 height of l1 hash - #[instrument(level = "trace", skip(self), err, ret)] - pub fn get_l1_height_of_l1_hash(&self, hash: [u8; 32]) -> Result, anyhow::Error> { - self.db.get::(&hash).map(|v| v.map(|a| a.0)) + match iter.next() { + Some(Ok(item)) => Ok(Some(item.into_tuple())), + Some(Err(e)) => Err(e), + _ => Ok(None), + } } - /// Sets the latest state diff - #[instrument(level = "trace", skip(self), err, ret)] - pub fn set_state_diff(&self, state_diff: StateDiff) -> anyhow::Result<()> { - let mut schema_batch = SchemaBatch::new(); - schema_batch.put::(&(), &state_diff)?; - - self.db.write_schemas(schema_batch)?; + /// Gets all transactions with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + #[instrument(level = "trace", skip(self), err)] + fn get_tx_range( + &self, + range: &std::ops::Range, + ) -> Result, anyhow::Error> { + self.get_data_range::(range) + } - Ok(()) + /// Gets the commitments in the da slot with given height if any + #[instrument(level = "trace", skip(self), err)] + fn get_commitments_on_da_slot( + &self, + height: u64, + ) -> anyhow::Result>> { + self.db.get::(&SlotNumber(height)) } /// Gets l1 height of l1 hash #[instrument(level = "trace", skip(self), err, ret)] - pub fn get_state_diff(&self) -> Result { - self.db - .get::(&()) - .map(|diff| diff.unwrap_or_default()) + fn get_l1_height_of_l1_hash(&self, hash: [u8; 32]) -> Result, anyhow::Error> { + self.db.get::(&hash).map(|v| v.map(|a| a.0)) } } diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs index d0a2cb951..bf204c787 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs @@ -29,7 +29,7 @@ const MAX_TRANSACTIONS_PER_REQUEST: u64 = 100; /// The maximum number of events that can be requested in a single RPC range query const MAX_EVENTS_PER_REQUEST: u64 = 500; -use super::LedgerDB; +use super::{LedgerDB, NodeLedgerOps, ProverLedgerOps, SharedLedgerOps}; impl LedgerRpcProvider for LedgerDB { fn get_slots( @@ -394,7 +394,7 @@ impl LedgerRpcProvider for LedgerDB { } fn get_prover_last_scanned_l1_height(&self) -> Result { - match self.get_prover_last_scanned_l1_height()? { + match ProverLedgerOps::get_prover_last_scanned_l1_height(self)? { Some(height) => Ok(height.0), None => Ok(0), } diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs new file mode 100644 index 000000000..29965e232 --- /dev/null +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs @@ -0,0 +1,216 @@ +use crate::schema::types::{ + BatchNumber, EventNumber, L2HeightRange, SlotNumber, StoredBatch, StoredSlot, StoredSoftBatch, + StoredStateTransition, StoredTransaction, TxNumber, +}; +use serde::de::DeserializeOwned; +use serde::Serialize; +use sov_rollup_interface::da::{DaSpec, SequencerCommitment}; +use sov_rollup_interface::services::da::SlotData; +use sov_rollup_interface::stf::{Event, SoftBatchReceipt, StateDiff}; +use sov_rollup_interface::zk::Proof; +use sov_schema_db::SchemaBatch; + +use super::{ItemNumbers, SlotCommit}; +use anyhow::Result; + +/// Shared ledger operations +pub trait SharedLedgerOps { + /// Put soft batch to db + fn put_soft_batch( + &self, + batch: &StoredSoftBatch, + batch_number: &BatchNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<()>; + + /// Put batch to db + fn put_batch( + &self, + batch: &StoredBatch, + batch_number: &BatchNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<()>; + + /// Put transaction to db + fn put_transaction( + &self, + tx: &StoredTransaction, + tx_number: &TxNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<()>; + + /// Put event to db + fn put_event( + &self, + event: &Event, + event_number: &EventNumber, + tx_number: TxNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<()>; + + /// Commits a soft batch to the database by inserting its transactions and batches before + fn commit_soft_batch( + &self, + batch_receipt: SoftBatchReceipt, + include_tx_body: bool, + ) -> Result<()>; + + /// Records the L2 height that was created as a soft confirmaiton of an L1 height + fn extend_l2_range_of_l1_slot( + &self, + l1_height: SlotNumber, + l2_height: BatchNumber, + ) -> Result<()>; + + /// Get the next slot, block, transaction, and event numbers + fn get_next_items_numbers(&self) -> ItemNumbers; + + /// Gets all slots with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + fn _get_slot_range(&self, range: &std::ops::Range) -> Result>; + + /// Gets all batches with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + fn get_batch_range(&self, range: &std::ops::Range) -> Result>; + + /// Gets l1 height of l1 hash + fn get_state_diff(&self) -> Result; + + /// Sets l1 height of l1 hash + fn set_l1_height_of_l1_hash(&self, hash: [u8; 32], height: u64) -> Result<()>; + + /// Saves a soft confirmation status for a given L1 height + fn put_soft_confirmation_status( + &self, + height: BatchNumber, + status: sov_rollup_interface::rpc::SoftConfirmationStatus, + ) -> Result<()>; + + /// Gets the commitments in the da slot with given height if any + /// Adds the new coming commitment info + fn update_commitments_on_da_slot( + &self, + height: u64, + commitment: SequencerCommitment, + ) -> Result<()>; + + /// Set the genesis state root + fn set_l2_genesis_state_root( + &self, + state_root: &StateRoot, + ) -> anyhow::Result<()>; + + /// Get the most recent committed soft batch, if any + fn get_head_soft_batch(&self) -> Result>; + + /// Gets all soft confirmations with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + fn get_soft_batch_range( + &self, + range: &std::ops::Range, + ) -> Result>; + + /// Gets all soft confirmations by numbers + fn get_soft_batch_by_number(&self, number: &BatchNumber) -> Result>; +} + +/// Node ledger operations +pub trait NodeLedgerOps: SharedLedgerOps { + /// Stores proof related data on disk, accessible via l1 slot height + fn update_verified_proof_data( + &self, + l1_height: u64, + proof: Proof, + state_transition: StoredStateTransition, + ) -> Result<()>; + + /// Get the most recent committed slot, if any + fn get_head_slot(&self) -> Result>; + + /// Gets all transactions with numbers `range.start` to `range.end`. If `range.end` is outside + /// the range of the database, the result will smaller than the requested range. + /// Note that this method blindly preallocates for the requested range, so it should not be exposed + /// directly via rpc. + fn get_tx_range(&self, range: &std::ops::Range) -> Result>; + + /// Gets the commitments in the da slot with given height if any + fn get_commitments_on_da_slot(&self, height: u64) -> Result>>; + + /// Gets l1 height of l1 hash + fn get_l1_height_of_l1_hash(&self, hash: [u8; 32]) -> Result>; +} + +/// Prover ledger operations +pub trait ProverLedgerOps: SharedLedgerOps { + /// Get the state root by L2 height + fn get_l2_state_root( + &self, + l2_height: u64, + ) -> anyhow::Result>; + + /// Get the last scanned slot by the prover + fn get_prover_last_scanned_l1_height(&self) -> Result>; + + /// Set the last scanned slot by the prover + /// Called by the prover. + fn set_prover_last_scanned_l1_height(&self, l1_height: SlotNumber) -> Result<()>; + + /// Get the witness by L2 height + fn get_l2_witness(&self, l2_height: u64) -> Result>; + + /// Stores proof related data on disk, accessible via l1 slot height + fn put_proof_data( + &self, + l1_height: u64, + l1_tx_id: [u8; 32], + proof: Proof, + state_transition: StoredStateTransition, + ) -> Result<()>; + + /// Set the witness by L2 height + fn set_l2_witness(&self, l2_height: u64, witness: &Witness) -> Result<()>; +} + +/// Sequencer ledger operations +pub trait SequencerLedgerOps: SharedLedgerOps { + /// Put slots + fn put_slot( + &self, + slot: &StoredSlot, + slot_number: &SlotNumber, + schema_batch: &mut SchemaBatch, + ) -> Result<()>; + + /// Commits a slot to the database by inserting its events, transactions, and batches before + /// inserting the slot metadata. + fn commit_slot( + &self, + data_to_commit: SlotCommit, + ) -> Result<()>; + + /// Used by the sequencer to record that it has committed to soft confirmations on a given L2 height + fn set_last_sequencer_commitment_l2_height(&self, l2_height: BatchNumber) -> Result<()>; + + /// Gets all pending commitments' l2 ranges. + /// Returns start-end L2 heights. + fn get_pending_commitments_l2_range(&self) -> Result>; + + /// Put a pending commitment l2 range + fn put_pending_commitment_l2_range(&self, l2_range: &L2HeightRange) -> Result<()>; + + /// Delete a pending commitment l2 range + fn delete_pending_commitment_l2_range(&self, l2_range: &L2HeightRange) -> Result<()>; + + /// Sets the latest state diff + fn set_state_diff(&self, state_diff: StateDiff) -> Result<()>; + + /// Get the most recent committed batch + /// Returns L2 height. + fn get_last_sequencer_commitment_l2_height(&self) -> anyhow::Result>; +} From bbac371652609277b5eb7483a47c98f051d8b933 Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:33:38 +0100 Subject: [PATCH 2/6] Propagate errors --- .../full-node/db/sov-db/src/ledger_db/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs index d0d7bc6be..3bcd9a02b 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs @@ -318,8 +318,7 @@ impl SharedLedgerOps for LedgerDB { let mut schema_batch = SchemaBatch::new(); schema_batch - .put::(&l1_height, &new_range) - .unwrap(); + .put::(&l1_height, &new_range)?; self.db.write_schemas(schema_batch)?; Ok(()) @@ -379,8 +378,7 @@ impl SharedLedgerOps for LedgerDB { let mut schema_batch = SchemaBatch::new(); schema_batch - .put::(&height, &status) - .unwrap(); + .put::(&height, &status)?; self.db.write_schemas(schema_batch)?; Ok(()) @@ -494,8 +492,7 @@ impl ProverLedgerOps for LedgerDB { let mut schema_batch = SchemaBatch::new(); schema_batch - .put::(&(), &l1_height) - .unwrap(); + .put::(&(), &l1_height)?; self.db.write_schemas(schema_batch)?; Ok(()) From 24022c6f3e360a451341ce897f9468930a9ddbc5 Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Thu, 25 Jul 2024 21:37:38 +0100 Subject: [PATCH 3/6] Cleanup generic --- crates/sequencer/src/commitment_controller.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/sequencer/src/commitment_controller.rs b/crates/sequencer/src/commitment_controller.rs index 03782baa4..bc675c292 100644 --- a/crates/sequencer/src/commitment_controller.rs +++ b/crates/sequencer/src/commitment_controller.rs @@ -19,8 +19,8 @@ pub struct CommitmentInfo { /// Returns none if the commitable L2 block range is shorter than `min_soft_confirmations_per_commitment` /// Returns `CommitmentInfo` if the sequencer should commit #[instrument(level = "debug", skip_all, fields(prev_l1_height), err)] -pub fn get_commitment_info( - ledger_db: &impl SequencerLedgerOps, +pub fn get_commitment_info( + ledger_db: &T, min_soft_confirmations_per_commitment: u64, state_diff_threshold_reached: bool, ) -> anyhow::Result> { From cd75d4a5f730c7af4e3e5268e4938a56f134d0f8 Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:43:52 +0200 Subject: [PATCH 4/6] Lint --- .../full-node/db/sov-db/src/ledger_db/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs index 3bcd9a02b..27cbe4bb0 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs @@ -317,8 +317,7 @@ impl SharedLedgerOps for LedgerDB { let mut schema_batch = SchemaBatch::new(); - schema_batch - .put::(&l1_height, &new_range)?; + schema_batch.put::(&l1_height, &new_range)?; self.db.write_schemas(schema_batch)?; Ok(()) @@ -377,8 +376,7 @@ impl SharedLedgerOps for LedgerDB { ) -> Result<(), anyhow::Error> { let mut schema_batch = SchemaBatch::new(); - schema_batch - .put::(&height, &status)?; + schema_batch.put::(&height, &status)?; self.db.write_schemas(schema_batch)?; Ok(()) @@ -491,8 +489,7 @@ impl ProverLedgerOps for LedgerDB { fn set_prover_last_scanned_l1_height(&self, l1_height: SlotNumber) -> anyhow::Result<()> { let mut schema_batch = SchemaBatch::new(); - schema_batch - .put::(&(), &l1_height)?; + schema_batch.put::(&(), &l1_height)?; self.db.write_schemas(schema_batch)?; Ok(()) From 80a830276499b3dbcab96262909dd1461d2c99d9 Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:57:59 +0200 Subject: [PATCH 5/6] Make lint --- crates/fullnode/src/runner.rs | 3 +-- crates/prover/src/runner.rs | 3 +-- crates/sequencer/src/sequencer.rs | 3 +-- .../full-node/db/sov-db/src/ledger_db/traits.rs | 10 +++++----- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crates/fullnode/src/runner.rs b/crates/fullnode/src/runner.rs index 786033675..951361135 100644 --- a/crates/fullnode/src/runner.rs +++ b/crates/fullnode/src/runner.rs @@ -14,8 +14,7 @@ use jsonrpsee::RpcModule; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; use sequencer_client::{GetSoftBatchResponse, SequencerClient}; -use sov_db::ledger_db::NodeLedgerOps; -use sov_db::ledger_db::SlotCommit; +use sov_db::ledger_db::{NodeLedgerOps, SlotCommit}; use sov_db::schema::types::{BatchNumber, SlotNumber, StoredSoftBatch, StoredStateTransition}; use sov_modules_api::Context; use sov_modules_stf_blueprint::StfBlueprintTrait; diff --git a/crates/prover/src/runner.rs b/crates/prover/src/runner.rs index 9d5339cb4..859e22d0f 100644 --- a/crates/prover/src/runner.rs +++ b/crates/prover/src/runner.rs @@ -16,8 +16,7 @@ use jsonrpsee::RpcModule; use rand::Rng; use sequencer_client::{GetSoftBatchResponse, SequencerClient}; use shared_backup_db::{DbPoolError, PostgresConnector, ProofType}; -use sov_db::ledger_db::ProverLedgerOps; -use sov_db::ledger_db::SlotCommit; +use sov_db::ledger_db::{ProverLedgerOps, SlotCommit}; use sov_db::schema::types::{BatchNumber, SlotNumber, StoredStateTransition}; use sov_modules_api::storage::HierarchicalStorageManager; use sov_modules_api::{BlobReaderTrait, Context, SignedSoftConfirmationBatch, SlotData}; diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index b491c22fb..5da911bf2 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -27,8 +27,7 @@ use shared_backup_db::{CommitmentStatus, PostgresConnector}; use soft_confirmation_rule_enforcer::SoftConfirmationRuleEnforcer; use sov_accounts::Accounts; use sov_accounts::Response::{AccountEmpty, AccountExists}; -use sov_db::ledger_db::SequencerLedgerOps; -use sov_db::ledger_db::SlotCommit; +use sov_db::ledger_db::{SequencerLedgerOps, SlotCommit}; use sov_db::schema::types::{BatchNumber, SlotNumber}; use sov_modules_api::hooks::HookSoftConfirmationInfo; use sov_modules_api::transaction::Transaction; diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs index 29965e232..33e800328 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs @@ -1,7 +1,4 @@ -use crate::schema::types::{ - BatchNumber, EventNumber, L2HeightRange, SlotNumber, StoredBatch, StoredSlot, StoredSoftBatch, - StoredStateTransition, StoredTransaction, TxNumber, -}; +use anyhow::Result; use serde::de::DeserializeOwned; use serde::Serialize; use sov_rollup_interface::da::{DaSpec, SequencerCommitment}; @@ -11,7 +8,10 @@ use sov_rollup_interface::zk::Proof; use sov_schema_db::SchemaBatch; use super::{ItemNumbers, SlotCommit}; -use anyhow::Result; +use crate::schema::types::{ + BatchNumber, EventNumber, L2HeightRange, SlotNumber, StoredBatch, StoredSlot, StoredSoftBatch, + StoredStateTransition, StoredTransaction, TxNumber, +}; /// Shared ledger operations pub trait SharedLedgerOps { From 64b80ba60c8d6a48e0ae79b2d934ca0159550279 Mon Sep 17 00:00:00 2001 From: jfldde <168934971+jfldde@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:17:01 +0200 Subject: [PATCH 6/6] Fix tests --- bin/citrea/src/test_rpc.rs | 2 +- crates/fullnode/tests/runner_initialization_tests.rs | 1 + crates/fullnode/tests/runner_reorg_tests.rs | 4 ++-- crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/citrea/src/test_rpc.rs b/bin/citrea/src/test_rpc.rs index a68cf781b..a1d87e59d 100644 --- a/bin/citrea/src/test_rpc.rs +++ b/bin/citrea/src/test_rpc.rs @@ -8,7 +8,7 @@ use proptest::{prop_compose, proptest}; use reqwest::header::CONTENT_TYPE; use serde_json::json; use sha2::Digest; -use sov_db::ledger_db::{LedgerDB, SlotCommit}; +use sov_db::ledger_db::{LedgerDB, SequencerLedgerOps, SharedLedgerOps, SlotCommit}; use sov_mock_da::MockDaSpec; #[cfg(test)] use sov_mock_da::{MockBlock, MockBlockHeader, MockHash}; diff --git a/crates/fullnode/tests/runner_initialization_tests.rs b/crates/fullnode/tests/runner_initialization_tests.rs index 46181c348..9d97e8c83 100644 --- a/crates/fullnode/tests/runner_initialization_tests.rs +++ b/crates/fullnode/tests/runner_initialization_tests.rs @@ -48,6 +48,7 @@ fn initialize_runner( MockDaService, MockZkvm, sov_modules_api::default_context::DefaultContext, + LedgerDB, > { let da_storage_path = storage_path.join("da").to_path_buf(); let rollup_storage_path = storage_path.join("rollup").to_path_buf(); diff --git a/crates/fullnode/tests/runner_reorg_tests.rs b/crates/fullnode/tests/runner_reorg_tests.rs index d89afb303..de50636d3 100644 --- a/crates/fullnode/tests/runner_reorg_tests.rs +++ b/crates/fullnode/tests/runner_reorg_tests.rs @@ -12,7 +12,7 @@ use sov_stf_runner::{ mod hash_stf; use hash_stf::{get_result_from_blocks, HashStf, Q, S}; -use sov_db::ledger_db::LedgerDB; +use sov_db::ledger_db::{LedgerDB, NodeLedgerOps}; use sov_mock_zkvm::MockCodeCommitment; use sov_prover_storage_manager::ProverStorageManager; use sov_rollup_interface::services::da::DaService; @@ -156,7 +156,7 @@ async fn runner_execution( }; let storage_manager = ProverStorageManager::new(storage_config).unwrap(); - let mut runner: CitreaFullnode<_, _, _, _, DefaultContext> = CitreaFullnode::new( + let mut runner: CitreaFullnode<_, _, _, _, DefaultContext, _> = CitreaFullnode::new( rollup_config.runner.unwrap(), rollup_config.public_keys, rollup_config.rpc, diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs index bf204c787..e5b6e87f2 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs @@ -625,7 +625,7 @@ mod tests { use sov_mock_da::{MockBlob, MockBlock}; use sov_rollup_interface::rpc::LedgerRpcProvider; - use crate::ledger_db::{LedgerDB, SlotCommit}; + use crate::ledger_db::{LedgerDB, SequencerLedgerOps, SlotCommit}; #[test] fn test_slot_subscription() { let temp_dir = tempfile::tempdir().unwrap();