diff --git a/crates/rooch/src/commands/da/commands/exec.rs b/crates/rooch/src/commands/da/commands/exec.rs index 53fb178fe4..63a094075f 100644 --- a/crates/rooch/src/commands/da/commands/exec.rs +++ b/crates/rooch/src/commands/da/commands/exec.rs @@ -526,7 +526,7 @@ impl ExecInner { } result = self .ledger_tx_getter - .load_ledger_tx_list(next_block_number, false) => { + .load_ledger_tx_list(next_block_number, false, true) => { let tx_list = result?; if tx_list.is_none() { if self.mode == ExecMode::Sync { diff --git a/crates/rooch/src/commands/da/commands/mod.rs b/crates/rooch/src/commands/da/commands/mod.rs index 6d927ab56d..dba5c7c9fb 100644 --- a/crates/rooch/src/commands/da/commands/mod.rs +++ b/crates/rooch/src/commands/da/commands/mod.rs @@ -41,6 +41,7 @@ pub mod index; pub mod namespace; pub mod pack; pub mod unpack; +pub mod verify; pub(crate) struct SequencedTxStore { tx_accumulator: MerkleAccumulator, @@ -425,6 +426,7 @@ impl LedgerTxGetter { &self, chunk_id: u128, must_has: bool, + verify_order: bool, ) -> anyhow::Result>> { let tx_list_opt = self .chunks @@ -445,7 +447,7 @@ impl LedgerTxGetter { self.segment_dir.clone(), chunk_id, segment_numbers.clone(), - true, + verify_order, )?; Ok(Some(tx_list)) }, @@ -927,7 +929,7 @@ impl TxPositionIndexer { while block_number <= stop_at { let tx_list = ledger_tx_loader - .load_ledger_tx_list(block_number, true) + .load_ledger_tx_list(block_number, true, true) .await?; let tx_list = tx_list.unwrap(); { diff --git a/crates/rooch/src/commands/da/commands/verify.rs b/crates/rooch/src/commands/da/commands/verify.rs new file mode 100644 index 0000000000..04722874db --- /dev/null +++ b/crates/rooch/src/commands/da/commands/verify.rs @@ -0,0 +1,53 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::da::commands::LedgerTxGetter; +use clap::Parser; +use rooch_types::error::RoochResult; +use std::path::PathBuf; + +/// Verify segments from segments directory. +/// Output: {expected_tx_order},{actual_tx_order},{tx_hash},{block_number} +#[derive(Debug, Parser)] +pub struct VerifyCommand { + #[clap(long = "segment-dir")] + pub segment_dir: PathBuf, + #[clap(long = "start-from", help = "Start from the specified block number")] + pub start_from: Option, +} + +impl VerifyCommand { + pub async fn execute(self) -> RoochResult<()> { + let segment_dir = self.segment_dir; + let ledger_tx_loader = LedgerTxGetter::new(segment_dir)?; + let stop_at = ledger_tx_loader.get_max_chunk_id(); + let mut block_number = self.start_from.unwrap_or(0); + + let mut expected_tx_order = 0; + + while block_number <= stop_at { + let tx_list = ledger_tx_loader + .load_ledger_tx_list(block_number, true, false) + .await?; + let tx_list = tx_list.unwrap(); + + if expected_tx_order == 0 { + expected_tx_order = tx_list.first().unwrap().sequence_info.tx_order; + } + + for mut ledger_tx in tx_list { + let tx_order = ledger_tx.sequence_info.tx_order; + let tx_hash = ledger_tx.tx_hash(); + if tx_order != expected_tx_order { + println!( + "{},{},{:?},{}", + expected_tx_order, tx_order, tx_hash, block_number + ); + } + expected_tx_order += 1; + } + block_number += 1; + } + Ok(()) + } +} diff --git a/crates/rooch/src/commands/da/mod.rs b/crates/rooch/src/commands/da/mod.rs index a39b016a3b..d405bb3259 100644 --- a/crates/rooch/src/commands/da/mod.rs +++ b/crates/rooch/src/commands/da/mod.rs @@ -9,6 +9,7 @@ use crate::commands::da::commands::index::IndexCommand; use crate::commands::da::commands::namespace::NamespaceCommand; use crate::commands::da::commands::pack::PackCommand; use crate::commands::da::commands::unpack::UnpackCommand; +use crate::commands::da::commands::verify::VerifyCommand; use async_trait::async_trait; use clap::Parser; use rooch_types::error::RoochResult; @@ -32,6 +33,10 @@ impl CommandAction for DA { index.execute().await?; Ok("".to_owned()) } + DACommand::Verify(verify) => { + verify.execute().await?; + Ok("".to_owned()) + } } } } @@ -44,4 +49,5 @@ pub enum DACommand { Namespace(NamespaceCommand), Exec(Box), Index(IndexCommand), + Verify(VerifyCommand), }