From cb3e221273e67e1f28679bcd63a14eef6ee1b9f7 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Tue, 30 May 2023 11:15:58 +0400 Subject: [PATCH] fix(stages): unwind receipts in execution stage (#2900) --- crates/stages/src/stages/execution.rs | 12 +++++++++++- crates/storage/provider/src/post_state/mod.rs | 4 +++- crates/storage/provider/src/transaction.rs | 4 +++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/stages/src/stages/execution.rs b/crates/stages/src/stages/execution.rs index 50074bf81f..aabeed188f 100644 --- a/crates/stages/src/stages/execution.rs +++ b/crates/stages/src/stages/execution.rs @@ -304,6 +304,14 @@ impl Stage for ExecutionStage { tx.delete::(key, None)?; } + // Look up the start index for the transaction range + let first_tx_num = tx.block_body_indices(*range.start())?.first_tx_num(); + + // Unwind all receipts for transactions in the block range + tx.unwind_table_by_num::(first_tx_num)?; + // `unwind_table_by_num` doesn't unwind the provided key, so we need to unwind it manually + tx.delete::(first_tx_num, None)?; + info!(target: "sync::stages::execution", to_block = input.unwind_to, unwind_progress = unwind_to, is_final_range, "Unwind iteration finished"); Ok(UnwindOutput { checkpoint: StageCheckpoint::new(unwind_to) }) } @@ -545,8 +553,10 @@ mod tests { assert_eq!( db_tx.get::(miner_acc), Ok(None), - "Third account should be unwinded" + "Third account should be unwound" ); + + assert_eq!(db_tx.get::(0), Ok(None), "First receipt should be unwound"); } #[tokio::test] diff --git a/crates/storage/provider/src/post_state/mod.rs b/crates/storage/provider/src/post_state/mod.rs index e5a686aafe..23106625c4 100644 --- a/crates/storage/provider/src/post_state/mod.rs +++ b/crates/storage/provider/src/post_state/mod.rs @@ -573,6 +573,7 @@ impl PostState { self.write_history_to_db(tx)?; // Write new storage state + tracing::trace!(target: "provider::post_state", len = self.storage.len(), "Writing new storage state"); let mut storages_cursor = tx.cursor_dup_write::()?; for (address, storage) in self.storage.into_iter() { // If the storage was wiped at least once, remove all previous entries from the @@ -613,13 +614,14 @@ impl PostState { } // Write bytecode - tracing::trace!(target: "provider::post_state", len = self.bytecode.len(), "Writing bytecods"); + tracing::trace!(target: "provider::post_state", len = self.bytecode.len(), "Writing bytecodes"); let mut bytecodes_cursor = tx.cursor_write::()?; for (hash, bytecode) in self.bytecode.into_iter() { bytecodes_cursor.upsert(hash, bytecode)?; } // Write the receipts of the transactions + tracing::trace!(target: "provider::post_state", len = self.receipts.len(), "Writing receipts"); let mut bodies_cursor = tx.cursor_read::()?; let mut receipts_cursor = tx.cursor_write::()?; for (block, receipts) in self.receipts { diff --git a/crates/storage/provider/src/transaction.rs b/crates/storage/provider/src/transaction.rs index 405979c3ff..7140c7e778 100644 --- a/crates/storage/provider/src/transaction.rs +++ b/crates/storage/provider/src/transaction.rs @@ -183,6 +183,8 @@ where /// Unwind table by some number key. /// Returns number of rows unwound. + /// + /// Note: Key is not inclusive and specified key would stay in db. #[inline] pub fn unwind_table_by_num(&self, num: u64) -> Result where @@ -192,7 +194,7 @@ where self.unwind_table::(num, |key| key) } - /// Unwind the table to a provided block. + /// Unwind the table to a provided number key. /// Returns number of rows unwound. /// /// Note: Key is not inclusive and specified key would stay in db.