mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-24 14:51:14 +00:00
Remove requirement on Hash = H256, make Proposer return StorageChanges and Proof (#3860)
* Extend `Proposer` to optionally generate a proof of the proposal * Something * Refactor sr-api to not depend on client anymore * Fix benches * Apply suggestions from code review Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Apply suggestions from code review * Introduce new `into_storage_changes` function * Switch to runtime api for `execute_block` and don't require `H256` anywhere in the code * Put the `StorageChanges` into the `Proposal` * Move the runtime api error to its own trait * Adds `StorageTransactionCache` to the runtime api This requires that we add `type NodeBlock = ` to the `impl_runtime_apis!` macro to work around some bugs in rustc :( * Remove `type NodeBlock` and switch to a "better" hack * Start using the transaction cache from the runtime api * Make it compile * Move `InMemory` to its own file * Make all tests work again * Return block, storage_changes and proof from Blockbuilder::bake() * Make sure that we use/set `storage_changes` when possible * Add test * Fix deadlock * Remove accidentally added folders * Introduce `RecordProof` as argument type to be more explicit * Update client/src/client.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Update primitives/state-machine/src/ext.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Integrates review feedback * Remove `unsafe` usage * Update client/block-builder/src/lib.rs Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org> * Update client/src/call_executor.rs * Bump versions Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
@@ -24,11 +24,13 @@ use sp_core::offchain::storage::{
|
||||
InMemOffchainStorage as OffchainStorage
|
||||
};
|
||||
use sp_runtime::generic::{BlockId, DigestItem};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, HasherFor};
|
||||
use sp_runtime::{Justification, Storage};
|
||||
use sp_state_machine::backend::{Backend as StateBackend, InMemory};
|
||||
use sp_state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction};
|
||||
use hash_db::{Hasher, Prefix};
|
||||
use sp_state_machine::{
|
||||
InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction,
|
||||
InMemoryBackend, Backend as StateBackend,
|
||||
};
|
||||
use hash_db::Prefix;
|
||||
use sp_trie::MemoryDB;
|
||||
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata};
|
||||
|
||||
@@ -459,25 +461,21 @@ impl<Block: BlockT> sc_client_api::light::Storage<Block> for Blockchain<Block>
|
||||
}
|
||||
|
||||
/// In-memory operation.
|
||||
pub struct BlockImportOperation<Block: BlockT, H: Hasher> {
|
||||
pub struct BlockImportOperation<Block: BlockT> {
|
||||
pending_block: Option<PendingBlock<Block>>,
|
||||
pending_cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||
old_state: InMemory<H>,
|
||||
new_state: Option<InMemory<H>>,
|
||||
changes_trie_update: Option<MemoryDB<H>>,
|
||||
old_state: InMemoryBackend<HasherFor<Block>>,
|
||||
new_state: Option<InMemoryBackend<HasherFor<Block>>>,
|
||||
changes_trie_update: Option<MemoryDB<HasherFor<Block>>>,
|
||||
aux: Vec<(Vec<u8>, Option<Vec<u8>>)>,
|
||||
finalized_blocks: Vec<(BlockId<Block>, Option<Justification>)>,
|
||||
set_head: Option<BlockId<Block>>,
|
||||
}
|
||||
|
||||
impl<Block, H> backend::BlockImportOperation<Block, H> for BlockImportOperation<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
|
||||
H::Out: Ord,
|
||||
impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> where
|
||||
Block::Hash: Ord,
|
||||
{
|
||||
type State = InMemory<H>;
|
||||
type State = InMemoryBackend<HasherFor<Block>>;
|
||||
|
||||
fn state(&self) -> sp_blockchain::Result<Option<&Self::State>> {
|
||||
Ok(Some(&self.old_state))
|
||||
@@ -502,17 +500,23 @@ where
|
||||
self.pending_cache = cache;
|
||||
}
|
||||
|
||||
fn update_db_storage(&mut self, update: <InMemory<H> as StateBackend<H>>::Transaction) -> sp_blockchain::Result<()> {
|
||||
fn update_db_storage(
|
||||
&mut self,
|
||||
update: <InMemoryBackend<HasherFor<Block>> as StateBackend<HasherFor<Block>>>::Transaction,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
self.new_state = Some(self.old_state.update(update));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> sp_blockchain::Result<()> {
|
||||
fn update_changes_trie(
|
||||
&mut self,
|
||||
update: ChangesTrieTransaction<HasherFor<Block>, NumberFor<Block>>,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
self.changes_trie_update = Some(update.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<H::Out> {
|
||||
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<Block::Hash> {
|
||||
check_genesis_storage(&storage)?;
|
||||
|
||||
let child_delta = storage.children.into_iter()
|
||||
@@ -524,7 +528,7 @@ where
|
||||
child_delta
|
||||
);
|
||||
|
||||
self.new_state = Some(InMemory::from(transaction));
|
||||
self.new_state = Some(InMemoryBackend::from(transaction));
|
||||
Ok(root)
|
||||
}
|
||||
|
||||
@@ -543,7 +547,11 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_finalized(&mut self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
|
||||
fn mark_finalized(
|
||||
&mut self,
|
||||
block: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
self.finalized_blocks.push((block, justification));
|
||||
Ok(())
|
||||
}
|
||||
@@ -559,26 +567,16 @@ where
|
||||
///
|
||||
/// > **Warning**: Doesn't support all the features necessary for a proper database. Only use this
|
||||
/// > struct for testing purposes. Do **NOT** use in production.
|
||||
pub struct Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{
|
||||
states: RwLock<HashMap<Block::Hash, InMemory<H>>>,
|
||||
changes_trie_storage: ChangesTrieStorage<Block, H>,
|
||||
pub struct Backend<Block: BlockT> where Block::Hash: Ord {
|
||||
states: RwLock<HashMap<Block::Hash, InMemoryBackend<HasherFor<Block>>>>,
|
||||
changes_trie_storage: ChangesTrieStorage<Block>,
|
||||
blockchain: Blockchain<Block>,
|
||||
import_lock: RwLock<()>,
|
||||
}
|
||||
|
||||
impl<Block, H> Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{
|
||||
impl<Block: BlockT> Backend<Block> where Block::Hash: Ord {
|
||||
/// Create a new instance of in-mem backend.
|
||||
pub fn new() -> Backend<Block, H> {
|
||||
pub fn new() -> Self {
|
||||
Backend {
|
||||
states: RwLock::new(HashMap::new()),
|
||||
changes_trie_storage: ChangesTrieStorage(InMemoryChangesTrieStorage::new()),
|
||||
@@ -588,12 +586,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, H> backend::AuxStore for Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{
|
||||
impl<Block: BlockT> backend::AuxStore for Backend<Block> where Block::Hash: Ord {
|
||||
fn insert_aux<
|
||||
'a,
|
||||
'b: 'a,
|
||||
@@ -609,16 +602,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, H> backend::Backend<Block, H> for Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{
|
||||
type BlockImportOperation = BlockImportOperation<Block, H>;
|
||||
impl<Block: BlockT> backend::Backend<Block> for Backend<Block> where Block::Hash: Ord {
|
||||
type BlockImportOperation = BlockImportOperation<Block>;
|
||||
type Blockchain = Blockchain<Block>;
|
||||
type State = InMemory<H>;
|
||||
type ChangesTrieStorage = ChangesTrieStorage<Block, H>;
|
||||
type State = InMemoryBackend<HasherFor<Block>>;
|
||||
type ChangesTrieStorage = ChangesTrieStorage<Block>;
|
||||
type OffchainStorage = OffchainStorage;
|
||||
|
||||
fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation> {
|
||||
@@ -635,7 +623,11 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
fn begin_state_operation(
|
||||
&self,
|
||||
operation: &mut Self::BlockImportOperation,
|
||||
block: BlockId<Block>,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
operation.old_state = self.state_at(block)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -680,7 +672,11 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
|
||||
fn finalize_block(
|
||||
&self,
|
||||
block: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
self.blockchain.finalize_header(block, justification)
|
||||
}
|
||||
|
||||
@@ -727,19 +723,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, H> backend::LocalBackend<Block, H> for Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{}
|
||||
impl<Block: BlockT> backend::LocalBackend<Block> for Backend<Block> where Block::Hash: Ord {}
|
||||
|
||||
impl<Block, H> backend::RemoteBackend<Block, H> for Backend<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
H::Out: Ord,
|
||||
{
|
||||
impl<Block: BlockT> backend::RemoteBackend<Block> for Backend<Block> where Block::Hash: Ord {
|
||||
fn is_local_state_available(&self, block: &BlockId<Block>) -> bool {
|
||||
self.blockchain.expect_block_number_from_id(block)
|
||||
.map(|num| num.is_zero())
|
||||
@@ -752,8 +738,11 @@ where
|
||||
}
|
||||
|
||||
/// Prunable in-memory changes trie storage.
|
||||
pub struct ChangesTrieStorage<Block: BlockT, H: Hasher>(InMemoryChangesTrieStorage<H, NumberFor<Block>>);
|
||||
impl<Block: BlockT, H: Hasher> backend::PrunableStateChangesTrieStorage<Block, H> for ChangesTrieStorage<Block, H> {
|
||||
pub struct ChangesTrieStorage<Block: BlockT>(
|
||||
InMemoryChangesTrieStorage<HasherFor<Block>, NumberFor<Block>>
|
||||
);
|
||||
|
||||
impl<Block: BlockT> backend::PrunableStateChangesTrieStorage<Block> for ChangesTrieStorage<Block> {
|
||||
fn oldest_changes_trie_block(
|
||||
&self,
|
||||
_config: &ChangesTrieConfiguration,
|
||||
@@ -763,45 +752,47 @@ impl<Block: BlockT, H: Hasher> backend::PrunableStateChangesTrieStorage<Block, H
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, H> sp_state_machine::ChangesTrieRootsStorage<H, NumberFor<Block>> for ChangesTrieStorage<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher,
|
||||
impl<Block: BlockT> sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>> for
|
||||
ChangesTrieStorage<Block>
|
||||
{
|
||||
fn build_anchor(
|
||||
&self,
|
||||
_hash: H::Out,
|
||||
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<H::Out, NumberFor<Block>>, String> {
|
||||
_hash: Block::Hash,
|
||||
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>, String> {
|
||||
Err("Dummy implementation".into())
|
||||
}
|
||||
|
||||
fn root(
|
||||
&self,
|
||||
_anchor: &ChangesTrieAnchorBlockId<H::Out, NumberFor<Block>>,
|
||||
_anchor: &ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>,
|
||||
_block: NumberFor<Block>,
|
||||
) -> Result<Option<H::Out>, String> {
|
||||
) -> Result<Option<Block::Hash>, String> {
|
||||
Err("Dummy implementation".into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, H> sp_state_machine::ChangesTrieStorage<H, NumberFor<Block>> for ChangesTrieStorage<Block, H>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher,
|
||||
impl<Block: BlockT> sp_state_machine::ChangesTrieStorage<HasherFor<Block>, NumberFor<Block>> for
|
||||
ChangesTrieStorage<Block>
|
||||
{
|
||||
fn as_roots_storage(&self) -> &dyn sp_state_machine::ChangesTrieRootsStorage<H, NumberFor<Block>> {
|
||||
fn as_roots_storage(&self)
|
||||
-> &dyn sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>>
|
||||
{
|
||||
self
|
||||
}
|
||||
|
||||
fn with_cached_changed_keys(
|
||||
&self,
|
||||
_root: &H::Out,
|
||||
_root: &Block::Hash,
|
||||
_functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<sp_state_machine::DBValue>, String> {
|
||||
fn get(
|
||||
&self,
|
||||
key: &Block::Hash,
|
||||
prefix: Prefix,
|
||||
) -> Result<Option<sp_state_machine::DBValue>, String> {
|
||||
self.0.get(key, prefix)
|
||||
}
|
||||
}
|
||||
@@ -823,10 +814,8 @@ pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> {
|
||||
mod tests {
|
||||
use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage};
|
||||
use std::sync::Arc;
|
||||
use substrate_test_runtime_client;
|
||||
use sp_core::Blake2Hasher;
|
||||
|
||||
type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend<substrate_test_runtime_client::runtime::Block, Blake2Hasher>;
|
||||
type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend<substrate_test_runtime_client::runtime::Block>;
|
||||
|
||||
#[test]
|
||||
fn test_leaves_with_complex_block_tree() {
|
||||
|
||||
Reference in New Issue
Block a user