paritytech / polkadot-sdk

The Parity Polkadot Blockchain SDK

Home Page:https://polkadot.network/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client::apply_block() has an awkward API

nazar-pc opened this issue · comments

While working with custom sync implementation for our chain I ended up in <Client as BlockImport>::import_block() implementation:

/// Import a checked and validated block.
///
/// NOTE: only use this implementation when there are NO consensus-level BlockImport
/// objects. Otherwise, importing blocks directly into the client would be bypassing
/// important verification work.
///
/// If you are not sure that there are no BlockImport objects provided by the consensus
/// algorithm, don't use this function.
async fn import_block(
&mut self,
mut import_block: BlockImportParams<Block>,
) -> Result<ImportResult, Self::Error> {
let span = tracing::span!(tracing::Level::DEBUG, "import_block");
let _enter = span.enter();
let storage_changes =
match self.prepare_block_storage_changes(&mut import_block).map_err(|e| {
warn!("Block prepare storage changes error: {}", e);
ConsensusError::ClientImport(e.to_string())
})? {
PrepareStorageChangesResult::Discard(res) => return Ok(res),
PrepareStorageChangesResult::Import(storage_changes) => storage_changes,
};
self.lock_import_and_run(|operation| {
self.apply_block(operation, import_block, storage_changes)
})
.map_err(|e| {
warn!("Block import error: {}", e);
ConsensusError::ClientImport(e.to_string())
})
}

What caught my eye is that Client::apply_block() method takes 3 arguments, two of which (import_block.state_action and storage_changes) can potentially contain storage changes, which is really confusing. I see that client always replaces state action with StateAction::Skip before actually calling Client::apply_block().

The fact that Client::apply_block() takes BlockImportParams as an argument seems like an accident because it intentionally skips state_action field internally, which likely means a different data structure should have been used there instead, but someone was lazy and decided to reuse existing data structure that almost worked.

This is basically a request to consider changing API into something a bit more clearer, possibly just duplicating BlockImportParams data structure without state_action field.