Set StateBackend::Transaction to PrefixedMemoryDB (#14612)

* Yep

* Try to get it working everywhere

* Make `from_raw_storage` start with an empty db

* More fixes!

* Make everything compile

* Fix `child_storage_root`

* Fix after merge

* Cleanups

* Update primitives/state-machine/src/overlayed_changes/mod.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Review comments

* Fix issues

* Silence warning

* FMT

* Clippy

---------

Co-authored-by: Davide Galassi <davxy@datawok.net>
This commit is contained in:
Bastian Köcher
2023-08-17 12:49:38 +02:00
committed by GitHub
parent a892fa7f92
commit ecf8035da6
67 changed files with 750 additions and 1150 deletions
@@ -119,9 +119,9 @@ pub struct BlockCheckParams<Block: BlockT> {
}
/// Precomputed storage.
pub enum StorageChanges<Block: BlockT, Transaction> {
pub enum StorageChanges<Block: BlockT> {
/// Changes coming from block execution.
Changes(sp_state_machine::StorageChanges<Transaction, HashingFor<Block>>),
Changes(sp_state_machine::StorageChanges<HashingFor<Block>>),
/// Whole new state.
Import(ImportedState<Block>),
}
@@ -142,9 +142,9 @@ impl<B: BlockT> std::fmt::Debug for ImportedState<B> {
}
/// Defines how a new state is computed for a given imported block.
pub enum StateAction<Block: BlockT, Transaction> {
pub enum StateAction<Block: BlockT> {
/// Apply precomputed changes coming from block execution or state sync.
ApplyChanges(StorageChanges<Block, Transaction>),
ApplyChanges(StorageChanges<Block>),
/// Execute block body (required) and compute state.
Execute,
/// Execute block body if parent state is available and compute state.
@@ -153,7 +153,7 @@ pub enum StateAction<Block: BlockT, Transaction> {
Skip,
}
impl<Block: BlockT, Transaction> StateAction<Block, Transaction> {
impl<Block: BlockT> StateAction<Block> {
/// Check if execution checks that require runtime calls should be skipped.
pub fn skip_execution_checks(&self) -> bool {
match self {
@@ -167,7 +167,7 @@ impl<Block: BlockT, Transaction> StateAction<Block, Transaction> {
/// Data required to import a Block.
#[non_exhaustive]
pub struct BlockImportParams<Block: BlockT, Transaction> {
pub struct BlockImportParams<Block: BlockT> {
/// Origin of the Block
pub origin: BlockOrigin,
/// The header, without consensus post-digests applied. This should be in the same
@@ -192,7 +192,7 @@ pub struct BlockImportParams<Block: BlockT, Transaction> {
/// Indexed transaction body of the block.
pub indexed_body: Option<Vec<Vec<u8>>>,
/// Specify how the new state is computed.
pub state_action: StateAction<Block, Transaction>,
pub state_action: StateAction<Block>,
/// Is this block finalized already?
/// `true` implies instant finality.
pub finalized: bool,
@@ -218,7 +218,7 @@ pub struct BlockImportParams<Block: BlockT, Transaction> {
pub post_hash: Option<Block::Hash>,
}
impl<Block: BlockT, Transaction> BlockImportParams<Block, Transaction> {
impl<Block: BlockT> BlockImportParams<Block> {
/// Create a new block import params.
pub fn new(origin: BlockOrigin, header: Block::Header) -> Self {
Self {
@@ -261,39 +261,6 @@ impl<Block: BlockT, Transaction> BlockImportParams<Block, Transaction> {
}
}
/// Auxiliary function for "converting" the transaction type.
///
/// Actually this just sets `StorageChanges::Changes` to `None` and makes rustc think that
/// `Self` now uses a different transaction type.
pub fn clear_storage_changes_and_mutate<Transaction2>(
self,
) -> BlockImportParams<Block, Transaction2> {
// Preserve imported state.
let state_action = match self.state_action {
StateAction::ApplyChanges(StorageChanges::Import(state)) =>
StateAction::ApplyChanges(StorageChanges::Import(state)),
StateAction::ApplyChanges(StorageChanges::Changes(_)) => StateAction::Skip,
StateAction::Execute => StateAction::Execute,
StateAction::ExecuteIfPossible => StateAction::ExecuteIfPossible,
StateAction::Skip => StateAction::Skip,
};
BlockImportParams {
origin: self.origin,
header: self.header,
justifications: self.justifications,
post_digests: self.post_digests,
body: self.body,
indexed_body: self.indexed_body,
state_action,
finalized: self.finalized,
auxiliary: self.auxiliary,
intermediates: self.intermediates,
fork_choice: self.fork_choice,
import_existing: self.import_existing,
post_hash: self.post_hash,
}
}
/// Insert intermediate by given key.
pub fn insert_intermediate<T: 'static + Send>(&mut self, key: &'static [u8], value: T) {
self.intermediates.insert(Cow::from(key), Box::new(value));
@@ -338,8 +305,6 @@ impl<Block: BlockT, Transaction> BlockImportParams<Block, Transaction> {
pub trait BlockImport<B: BlockT> {
/// The error type.
type Error: std::error::Error + Send + 'static;
/// The transaction type used by the backend.
type Transaction: Send + 'static;
/// Check block preconditions.
async fn check_block(
@@ -350,17 +315,13 @@ pub trait BlockImport<B: BlockT> {
/// Import a block.
async fn import_block(
&mut self,
block: BlockImportParams<B, Self::Transaction>,
block: BlockImportParams<B>,
) -> Result<ImportResult, Self::Error>;
}
#[async_trait::async_trait]
impl<B: BlockT, Transaction> BlockImport<B> for crate::import_queue::BoxBlockImport<B, Transaction>
where
Transaction: Send + 'static,
{
impl<B: BlockT> BlockImport<B> for crate::import_queue::BoxBlockImport<B> {
type Error = sp_consensus::error::Error;
type Transaction = Transaction;
/// Check block preconditions.
async fn check_block(
@@ -373,21 +334,19 @@ where
/// Import a block.
async fn import_block(
&mut self,
block: BlockImportParams<B, Transaction>,
block: BlockImportParams<B>,
) -> Result<ImportResult, Self::Error> {
(**self).import_block(block).await
}
}
#[async_trait::async_trait]
impl<B: BlockT, T, E: std::error::Error + Send + 'static, Transaction> BlockImport<B> for Arc<T>
impl<B: BlockT, T, E: std::error::Error + Send + 'static> BlockImport<B> for Arc<T>
where
for<'r> &'r T: BlockImport<B, Error = E, Transaction = Transaction>,
for<'r> &'r T: BlockImport<B, Error = E>,
T: Send + Sync,
Transaction: Send + 'static,
{
type Error = E;
type Transaction = Transaction;
async fn check_block(
&mut self,
@@ -398,7 +357,7 @@ where
async fn import_block(
&mut self,
block: BlockImportParams<B, Transaction>,
block: BlockImportParams<B>,
) -> Result<ImportResult, Self::Error> {
(&**self).import_block(block).await
}
@@ -50,16 +50,14 @@ const LOG_TARGET: &str = "sync::import-queue";
/// A commonly-used Import Queue type.
///
/// This defines the transaction type of the `BasicQueue` to be the transaction type for a client.
pub type DefaultImportQueue<Block, Client> =
BasicQueue<Block, sp_api::TransactionFor<Client, Block>>;
pub type DefaultImportQueue<Block> = BasicQueue<Block>;
mod basic_queue;
pub mod buffered_link;
pub mod mock;
/// Shared block import struct used by the queue.
pub type BoxBlockImport<B, Transaction> =
Box<dyn BlockImport<B, Error = ConsensusError, Transaction = Transaction> + Send + Sync>;
pub type BoxBlockImport<B> = Box<dyn BlockImport<B, Error = ConsensusError> + Send + Sync>;
/// Shared justification import struct used by the queue.
pub type BoxJustificationImport<B> =
@@ -98,10 +96,8 @@ pub struct IncomingBlock<B: BlockT> {
pub trait Verifier<B: BlockT>: Send {
/// Verify the given block data and return the `BlockImportParams` to
/// continue the block import process.
async fn verify(
&mut self,
block: BlockImportParams<B, ()>,
) -> Result<BlockImportParams<B, ()>, String>;
async fn verify(&mut self, block: BlockImportParams<B>)
-> Result<BlockImportParams<B>, String>;
}
/// Blocks import queue API.
@@ -221,8 +217,8 @@ pub enum BlockImportError {
type BlockImportResult<B> = Result<BlockImportStatus<NumberFor<B>>, BlockImportError>;
/// Single block import function.
pub async fn import_single_block<B: BlockT, V: Verifier<B>, Transaction: Send + 'static>(
import_handle: &mut impl BlockImport<B, Transaction = Transaction, Error = ConsensusError>,
pub async fn import_single_block<B: BlockT, V: Verifier<B>>(
import_handle: &mut impl BlockImport<B, Error = ConsensusError>,
block_origin: BlockOrigin,
block: IncomingBlock<B>,
verifier: &mut V,
@@ -231,12 +227,8 @@ pub async fn import_single_block<B: BlockT, V: Verifier<B>, Transaction: Send +
}
/// Single block import function with metering.
pub(crate) async fn import_single_block_metered<
B: BlockT,
V: Verifier<B>,
Transaction: Send + 'static,
>(
import_handle: &mut impl BlockImport<B, Transaction = Transaction, Error = ConsensusError>,
pub(crate) async fn import_single_block_metered<B: BlockT, V: Verifier<B>>(
import_handle: &mut impl BlockImport<B, Error = ConsensusError>,
block_origin: BlockOrigin,
block: IncomingBlock<B>,
verifier: &mut V,
@@ -350,7 +342,6 @@ pub(crate) async fn import_single_block_metered<
metrics.report_verification(true, started.elapsed());
}
let import_block = import_block.clear_storage_changes_and_mutate();
let imported = import_handle.import_block(import_block).await;
if let Some(metrics) = metrics.as_ref() {
metrics.report_verification_and_import(started.elapsed());
@@ -28,7 +28,7 @@ use sp_runtime::{
traits::{Block as BlockT, Header as HeaderT, NumberFor},
Justification, Justifications,
};
use std::{marker::PhantomData, pin::Pin, time::Duration};
use std::{pin::Pin, time::Duration};
use crate::{
import_queue::{
@@ -42,15 +42,14 @@ use crate::{
/// Interface to a basic block import queue that is importing blocks sequentially in a separate
/// task, with plugable verification.
pub struct BasicQueue<B: BlockT, Transaction> {
pub struct BasicQueue<B: BlockT> {
/// Handle for sending justification and block import messages to the background task.
handle: BasicQueueHandle<B>,
/// Results coming from the worker task.
result_port: BufferedLinkReceiver<B>,
_phantom: PhantomData<Transaction>,
}
impl<B: BlockT, Transaction> Drop for BasicQueue<B, Transaction> {
impl<B: BlockT> Drop for BasicQueue<B> {
fn drop(&mut self) {
// Flush the queue and close the receiver to terminate the future.
self.handle.close();
@@ -58,13 +57,13 @@ impl<B: BlockT, Transaction> Drop for BasicQueue<B, Transaction> {
}
}
impl<B: BlockT, Transaction: Send + 'static> BasicQueue<B, Transaction> {
impl<B: BlockT> BasicQueue<B> {
/// Instantiate a new basic queue, with given verifier.
///
/// This creates a background task, and calls `on_start` on the justification importer.
pub fn new<V: 'static + Verifier<B>>(
verifier: V,
block_import: BoxBlockImport<B, Transaction>,
block_import: BoxBlockImport<B>,
justification_import: Option<BoxJustificationImport<B>>,
spawner: &impl sp_core::traits::SpawnEssentialNamed,
prometheus_registry: Option<&Registry>,
@@ -96,7 +95,6 @@ impl<B: BlockT, Transaction: Send + 'static> BasicQueue<B, Transaction> {
Self {
handle: BasicQueueHandle::new(justification_sender, block_import_sender),
result_port,
_phantom: PhantomData,
}
}
}
@@ -165,7 +163,7 @@ impl<B: BlockT> ImportQueueService<B> for BasicQueueHandle<B> {
}
#[async_trait::async_trait]
impl<B: BlockT, Transaction: Send> ImportQueue<B> for BasicQueue<B, Transaction> {
impl<B: BlockT> ImportQueue<B> for BasicQueue<B> {
/// Get handle to [`ImportQueueService`].
fn service(&self) -> Box<dyn ImportQueueService<B>> {
Box::new(self.handle.clone())
@@ -220,8 +218,8 @@ mod worker_messages {
/// to give other futures the possibility to be run.
///
/// Returns when `block_import` ended.
async fn block_import_process<B: BlockT, Transaction: Send + 'static>(
mut block_import: BoxBlockImport<B, Transaction>,
async fn block_import_process<B: BlockT>(
mut block_import: BoxBlockImport<B>,
mut verifier: impl Verifier<B>,
mut result_sender: BufferedLinkSender<B>,
mut block_import_receiver: TracingUnboundedReceiver<worker_messages::ImportBlocks<B>>,
@@ -262,10 +260,10 @@ struct BlockImportWorker<B: BlockT> {
}
impl<B: BlockT> BlockImportWorker<B> {
fn new<V: 'static + Verifier<B>, Transaction: Send + 'static>(
fn new<V: 'static + Verifier<B>>(
result_sender: BufferedLinkSender<B>,
verifier: V,
block_import: BoxBlockImport<B, Transaction>,
block_import: BoxBlockImport<B>,
justification_import: Option<BoxJustificationImport<B>>,
metrics: Option<Metrics>,
) -> (
@@ -391,8 +389,8 @@ struct ImportManyBlocksResult<B: BlockT> {
///
/// This will yield after each imported block once, to ensure that other futures can
/// be called as well.
async fn import_many_blocks<B: BlockT, V: Verifier<B>, Transaction: Send + 'static>(
import_handle: &mut BoxBlockImport<B, Transaction>,
async fn import_many_blocks<B: BlockT, V: Verifier<B>>(
import_handle: &mut BoxBlockImport<B>,
blocks_origin: BlockOrigin,
blocks: Vec<IncomingBlock<B>>,
verifier: &mut V,
@@ -507,14 +505,14 @@ mod tests {
import_queue::Verifier,
};
use futures::{executor::block_on, Future};
use sp_test_primitives::{Block, BlockNumber, Extrinsic, Hash, Header};
use sp_test_primitives::{Block, BlockNumber, Hash, Header};
#[async_trait::async_trait]
impl Verifier<Block> for () {
async fn verify(
&mut self,
block: BlockImportParams<Block, ()>,
) -> Result<BlockImportParams<Block, ()>, String> {
block: BlockImportParams<Block>,
) -> Result<BlockImportParams<Block>, String> {
Ok(BlockImportParams::new(block.origin, block.header))
}
}
@@ -522,7 +520,6 @@ mod tests {
#[async_trait::async_trait]
impl BlockImport<Block> for () {
type Error = sp_consensus::Error;
type Transaction = Extrinsic;
async fn check_block(
&mut self,
@@ -533,7 +530,7 @@ mod tests {
async fn import_block(
&mut self,
_block: BlockImportParams<Block, Self::Transaction>,
_block: BlockImportParams<Block>,
) -> Result<ImportResult, Self::Error> {
Ok(ImportResult::imported(true))
}