Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce API for directly importing the state into the database #5956

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions substrate/client/api/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ pub trait BlockImportOperation<Block: BlockT> {

/// Configure whether to create a block gap if newly imported block is missing parent
fn set_create_gap(&mut self, create_gap: bool);

/// Configure whether to commit the state changes to the underlying database.
fn set_commit_state(&mut self, commit: bool);
}

/// Interface for performing operations on the backend.
Expand Down Expand Up @@ -590,6 +593,27 @@ pub trait Backend<Block: BlockT>: AuxStore + Send + Sync {
/// Returns state backend with post-state of given block.
fn state_at(&self, hash: Block::Hash) -> sp_blockchain::Result<Self::State>;

/// Import the state changes directly to the database.
///
/// # Arguments
///
/// - `at`: The block hash corresponding to the last available state before updating the trie
/// database.
/// - `storage`: The storage changes reflecting the transition from the last local state to the
/// target block's state being imported.
/// - `state_version`: The state version of the target block, which is resolved from the
/// provided `storage` data.
///
/// # Returns
///
/// Returns the state root after importing the state.
fn import_state(
&self,
at: Block::Hash,
storage: sp_runtime::Storage,
state_version: sp_runtime::StateVersion,
) -> sp_blockchain::Result<Block::Hash>;

/// Attempts to revert the chain by `n` blocks. If `revert_finalized` is set it will attempt to
/// revert past any finalized block, this is unsafe and can potentially leave the node in an
/// inconsistent state. All blocks higher than the best block are also reverted and not counting
Expand Down
23 changes: 17 additions & 6 deletions substrate/client/api/src/in_mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ impl<Block: BlockT> Blockchain<Block> {
pub fn equals_to(&self, other: &Self) -> bool {
// Check ptr equality first to avoid double read locks.
if ptr::eq(self, other) {
return true
return true;
}
self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks
}
Expand All @@ -201,7 +201,7 @@ impl<Block: BlockT> Blockchain<Block> {
pub fn canon_equals_to(&self, other: &Self) -> bool {
// Check ptr equality first to avoid double read locks.
if ptr::eq(self, other) {
return true
return true;
}
let this = self.storage.read();
let other = other.storage.read();
Expand Down Expand Up @@ -307,7 +307,7 @@ impl<Block: BlockT> Blockchain<Block> {
if !stored_justifications.append(justification) {
return Err(sp_blockchain::Error::BadJustification(
"Duplicate consensus engine ID".into(),
))
));
}
} else {
*block_justifications = Some(Justifications::from(justification));
Expand Down Expand Up @@ -586,6 +586,8 @@ impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperatio
}

fn set_create_gap(&mut self, _create_gap: bool) {}

fn set_commit_state(&mut self, _commit: bool) {}
}

/// In-memory backend. Keeps all states and blocks in memory.
Expand Down Expand Up @@ -736,7 +738,7 @@ impl<Block: BlockT> backend::Backend<Block> for Backend<Block> {

fn state_at(&self, hash: Block::Hash) -> sp_blockchain::Result<Self::State> {
if hash == Default::default() {
return Ok(Self::State::default())
return Ok(Self::State::default());
}

self.states
Expand All @@ -746,6 +748,15 @@ impl<Block: BlockT> backend::Backend<Block> for Backend<Block> {
.ok_or_else(|| sp_blockchain::Error::UnknownBlock(format!("{}", hash)))
}

fn import_state(
&self,
_at: Block::Hash,
_storage: sp_runtime::Storage,
_state_version: sp_runtime::StateVersion,
) -> sp_blockchain::Result<Block::Hash> {
unimplemented!("Not needed for in-mem backend")
}

fn revert(
&self,
_n: NumberFor<Block>,
Expand Down Expand Up @@ -783,15 +794,15 @@ impl<Block: BlockT> backend::LocalBackend<Block> for Backend<Block> {}
/// Check that genesis storage is valid.
pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> {
if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
return Err(sp_blockchain::Error::InvalidState)
return Err(sp_blockchain::Error::InvalidState);
}

if storage
.children_default
.keys()
.any(|child_key| !well_known_keys::is_child_storage_key(child_key))
{
return Err(sp_blockchain::Error::InvalidState)
return Err(sp_blockchain::Error::InvalidState);
}

Ok(())
Expand Down
1 change: 1 addition & 0 deletions substrate/client/db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ sp-core = { workspace = true, default-features = true }
sp-database = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-state-machine = { workspace = true, default-features = true }
sp-storage = { workspace = true, default-features = true }
sp-trie = { workspace = true, default-features = true }

[dev-dependencies]
Expand Down
Loading
Loading