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:
Bastian Köcher
2020-01-10 10:48:32 +01:00
committed by GitHub
parent 74d6e660c6
commit fd6b29dd2c
140 changed files with 4860 additions and 3339 deletions
+40 -23
View File
@@ -24,16 +24,16 @@ use authorship::claim_slot;
use sp_consensus_babe::{AuthorityPair, SlotNumber};
use sc_block_builder::BlockBuilder;
use sp_consensus::NoNetwork as DummyOracle;
use sp_consensus::import_queue::{
BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport,
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, RecordProof,
import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport},
};
use sc_network_test::*;
use sc_network_test::{Block as TestBlock, PeersClient};
use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig};
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
use tokio::runtime::current_thread;
use sc_client_api::BlockchainEvents;
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
use log::debug;
use std::{time::Duration, cell::RefCell};
@@ -94,16 +94,25 @@ impl Environment<TestBlock> for DummyFactory {
impl DummyProposer {
fn propose_with(&mut self, pre_digests: DigestFor<TestBlock>)
-> future::Ready<Result<TestBlock, Error>>
-> future::Ready<
Result<
Proposal<
TestBlock,
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>
>,
Error
>
>
{
use codec::Encode;
let block_builder = self.factory.client.new_block_at(
&BlockId::Hash(self.parent_hash),
pre_digests,
false,
).unwrap();
let mut block = match block_builder.bake().map_err(|e| e.into()) {
Ok(b) => b,
let mut block = match block_builder.build().map_err(|e| e.into()) {
Ok(b) => b.block,
Err(e) => return future::ready(Err(e)),
};
@@ -142,20 +151,22 @@ impl DummyProposer {
// mutate the block header according to the mutator.
(self.factory.mutator)(&mut block.header, Stage::PreSeal);
future::ready(Ok(block))
future::ready(Ok(Proposal { block, proof: None, storage_changes: Default::default() }))
}
}
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = future::Ready<Result<TestBlock, Error>>;
type Transaction = sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
fn propose(
&mut self,
_: InherentData,
pre_digests: DigestFor<TestBlock>,
_: Duration,
) -> Self::Create {
_: RecordProof,
) -> Self::Proposal {
self.propose_with(pre_digests)
}
}
@@ -169,10 +180,11 @@ struct PanickingBlockImport<B>(B);
impl<B: BlockImport<TestBlock>> BlockImport<TestBlock> for PanickingBlockImport<B> {
type Error = B::Error;
type Transaction = B::Transaction;
fn import_block(
&mut self,
block: BlockImportParams<TestBlock>,
block: BlockImportParams<TestBlock, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
Ok(self.0.import_block(block, new_cache).expect("importing block failed"))
@@ -214,7 +226,7 @@ impl Verifier<TestBlock> for TestVerifier {
mut header: TestHeader,
justification: Option<Justification>,
body: Option<Vec<TestExtrinsic>>,
) -> Result<(BlockImportParams<TestBlock>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<TestBlock, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
// apply post-sealing mutations (i.e. stripping seal, if desired).
(self.mutator)(&mut header, Stage::PostSeal);
Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!"))
@@ -224,7 +236,9 @@ impl Verifier<TestBlock> for TestVerifier {
pub struct PeerData {
link: BabeLink<TestBlock>,
inherent_data_providers: InherentDataProviders,
block_import: Mutex<Option<BoxBlockImport<TestBlock>>>,
block_import: Mutex<
Option<BoxBlockImport<TestBlock, TransactionFor<substrate_test_runtime_client::Backend, TestBlock>>>
>,
}
impl TestNetFactory for BabeTestNet {
@@ -240,9 +254,9 @@ impl TestNetFactory for BabeTestNet {
}
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -262,9 +276,11 @@ impl TestNetFactory for BabeTestNet {
let block_import = PanickingBlockImport(block_import);
let data_block_import = Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_>));
let data_block_import = Mutex::new(
Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>)
);
(
Box::new(block_import),
BlockImportAdapter::new_full(block_import),
None,
None,
None,
@@ -322,8 +338,8 @@ impl TestNetFactory for BabeTestNet {
fn rejects_empty_block() {
env_logger::try_init().unwrap();
let mut net = BabeTestNet::new(3);
let block_builder = |builder: BlockBuilder<_, _>| {
builder.bake().unwrap()
let block_builder = |builder: BlockBuilder<_, _, _>| {
builder.build().unwrap().block
};
net.mut_peers(|peer| {
peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder);
@@ -525,12 +541,12 @@ fn can_author_block() {
}
// Propose and import a new BABE block on top of the given parent.
fn propose_and_import_block(
fn propose_and_import_block<Transaction>(
parent: &TestHeader,
slot_number: Option<SlotNumber>,
proposer_factory: &mut DummyFactory,
block_import: &mut BoxBlockImport<TestBlock>,
) -> H256 {
block_import: &mut BoxBlockImport<TestBlock, Transaction>,
) -> sp_core::H256 {
let mut proposer = proposer_factory.init(parent).unwrap();
let slot_number = slot_number.unwrap_or_else(|| {
@@ -549,7 +565,7 @@ fn propose_and_import_block(
],
};
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap();
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block;
let seal = {
// sign the pre-sealed hash of the block and then
@@ -574,6 +590,7 @@ fn propose_and_import_block(
justification: None,
post_digests: vec![seal],
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,