diff --git a/substrate/client/api/src/backend.rs b/substrate/client/api/src/backend.rs index 0b2a34952401..f645ed61b944 100644 --- a/substrate/client/api/src/backend.rs +++ b/substrate/client/api/src/backend.rs @@ -551,6 +551,7 @@ pub trait Backend: AuxStore + Send + Sync { &self, hash: Block::Hash, justification: Option, + ensure_sequential_finalization: bool, ) -> sp_blockchain::Result<()>; /// Append justification to the block with the given `hash`. diff --git a/substrate/client/api/src/in_mem.rs b/substrate/client/api/src/in_mem.rs index 8bae4bc65a62..7e9e7834a9b0 100644 --- a/substrate/client/api/src/in_mem.rs +++ b/substrate/client/api/src/in_mem.rs @@ -712,6 +712,7 @@ impl backend::Backend for Backend { &self, hash: Block::Hash, justification: Option, + _ensure_sequesntial_finalization: bool, ) -> sp_blockchain::Result<()> { self.blockchain.finalize_header(hash, justification) } diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index bd24fdde809d..4ca2aaecf38c 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -1380,10 +1380,13 @@ impl Backend { justification: Option, current_transaction_justifications: &mut HashMap, remove_displaced: bool, + ensure_sequential_finalization: bool, ) -> ClientResult> { // TODO: ensure best chain contains this block. let number = *header.number(); - self.ensure_sequential_finalization(header, last_finalized)?; + if ensure_sequential_finalization { + self.ensure_sequential_finalization(header, last_finalized)?; + } let with_state = sc_client_api::Backend::have_state_at(self, hash, number); self.note_finalized( @@ -1481,6 +1484,7 @@ impl Backend { justification, &mut current_transaction_justifications, finalized_blocks.peek().is_none(), + true, )?); last_finalized_hash = block_hash; last_finalized_num = *block_header.number(); @@ -2114,6 +2118,7 @@ impl sc_client_api::backend::Backend for Backend { &self, hash: Block::Hash, justification: Option, + ensure_sequential_finalization: bool, ) -> ClientResult<()> { let mut transaction = Transaction::new(); let header = self.blockchain.expect_header(hash)?; @@ -2127,6 +2132,7 @@ impl sc_client_api::backend::Backend for Backend { justification, &mut current_transaction_justifications, true, + ensure_sequential_finalization, )?; self.storage.db.commit(transaction)?; diff --git a/substrate/client/service/src/client/client.rs b/substrate/client/service/src/client/client.rs index 55d91b322ea7..d88c28a3e793 100644 --- a/substrate/client/service/src/client/client.rs +++ b/substrate/client/service/src/client/client.rs @@ -128,6 +128,10 @@ where fn clear_block_gap(&self) -> sp_blockchain::Result<()> { self.backend.blockchain().clear_block_gap() } + + fn finalize_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()> { + self.backend.finalize_block(hash, None, false) + } } /// Used in importing a block, where additional changes are made after the runtime diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index 5b6f3a63bc81..912e373f2fa4 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -106,6 +106,9 @@ pub struct RpcHandlers(Arc>); pub trait ClientExt> { /// Clear block gap after initial block insertion. fn clear_block_gap(&self) -> sp_blockchain::Result<()>; + + /// Finalize block disabling sequential order check. + fn finalize_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>; } impl RpcHandlers { diff --git a/substrate/primitives/blockchain/src/backend.rs b/substrate/primitives/blockchain/src/backend.rs index fc47413c24c2..01ff9d22493f 100644 --- a/substrate/primitives/blockchain/src/backend.rs +++ b/substrate/primitives/blockchain/src/backend.rs @@ -17,7 +17,7 @@ //! Substrate blockchain trait -use log::warn; +use log::{debug, warn}; use parking_lot::RwLock; use sp_runtime::{ generic::BlockId, @@ -289,9 +289,14 @@ pub trait Backend: match finalized_chain.iter().rev().nth(distance_from_finalized as usize) { Some(header) => (header.number, header.hash), None => { - let header = self.header_metadata( - finalized_chain.front().expect("Not empty; qed").parent, - )?; + let parent = finalized_chain.front().expect("Not empty; qed").parent; + let header = match self.header_metadata(parent) { + Ok(header) => header, + Err(_) => { + debug!("Can't find obtain header metatadata: {parent:?}"); + break; + }, + }; let result = (header.number, header.hash); finalized_chain.push_front(header); result