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
@@ -31,7 +31,9 @@
use std::sync::Arc;
use std::time::Duration;
use sp_runtime::{traits::{Block as BlockT, DigestFor}, generic::BlockId};
use sp_runtime::{
generic::BlockId, traits::{Block as BlockT, DigestFor, NumberFor, HasherFor},
};
use futures::prelude::*;
pub use sp_inherents::InherentData;
@@ -48,10 +50,11 @@ const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512;
pub use self::error::Error;
pub use block_import::{
BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, ImportResult,
JustificationImport, FinalityProofImport,
BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams,
ImportResult, JustificationImport, FinalityProofImport,
};
pub use select_chain::SelectChain;
pub use sp_state_machine::Backend as StateBackend;
/// Block status.
#[derive(Debug, PartialEq, Eq)]
@@ -71,14 +74,56 @@ pub enum BlockStatus {
/// Environment producer for a Consensus instance. Creates proposer instance and communication streams.
pub trait Environment<B: BlockT> {
/// The proposer type this creates.
type Proposer: Proposer<B>;
type Proposer: Proposer<B> + 'static;
/// Error which can occur upon creation.
type Error: From<Error>;
type Error: From<Error> + std::fmt::Debug + 'static;
/// Initialize the proposal logic on top of a specific header. Provide
/// the authorities at that header.
fn init(&mut self, parent_header: &B::Header)
-> Result<Self::Proposer, Self::Error>;
fn init(&mut self, parent_header: &B::Header) -> Result<Self::Proposer, Self::Error>;
}
/// A proposal that is created by a [`Proposer`].
pub struct Proposal<Block: BlockT, Transaction> {
/// The block that was build.
pub block: Block,
/// Optional proof that was recorded while building the block.
pub proof: Option<sp_state_machine::StorageProof>,
/// The storage changes while building this block.
pub storage_changes: sp_state_machine::StorageChanges<Transaction, HasherFor<Block>, NumberFor<Block>>,
}
/// Used as parameter to [`Proposer`] to tell the requirement on recording a proof.
///
/// When `RecordProof::Yes` is given, all accessed trie nodes should be saved. These recorded
/// trie nodes can be used by a third party to proof this proposal without having access to the
/// full storage.
#[derive(Copy, Clone, PartialEq)]
pub enum RecordProof {
/// `Yes`, record a proof.
Yes,
/// `No`, don't record any proof.
No,
}
impl RecordProof {
/// Returns if `Self` == `Yes`.
pub fn yes(&self) -> bool {
match self {
Self::Yes => true,
Self::No => false,
}
}
}
impl From<bool> for RecordProof {
fn from(val: bool) -> Self {
if val {
Self::Yes
} else {
Self::No
}
}
}
/// Logic for a proposer.
@@ -89,16 +134,29 @@ pub trait Environment<B: BlockT> {
/// Proposers are generic over bits of "consensus data" which are engine-specific.
pub trait Proposer<B: BlockT> {
/// Error type which can occur when proposing or evaluating.
type Error: From<Error> + ::std::fmt::Debug + 'static;
/// Future that resolves to a committed proposal.
type Create: Future<Output = Result<B, Self::Error>>;
type Error: From<Error> + std::fmt::Debug + 'static;
/// The transaction type used by the backend.
type Transaction: Default + Send + 'static;
/// Future that resolves to a committed proposal with an optional proof.
type Proposal: Future<Output = Result<Proposal<B, Self::Transaction>, Self::Error>> +
Send + Unpin + 'static;
/// Create a proposal.
///
/// Gets the `inherent_data` and `inherent_digests` as input for the proposal. Additionally
/// a maximum duration for building this proposal is given. If building the proposal takes
/// longer than this maximum, the proposal will be very likely discarded.
///
/// # Return
///
/// Returns a future that resolves to a [`Proposal`] or to [`Self::Error`].
fn propose(
&mut self,
inherent_data: InherentData,
inherent_digests: DigestFor<B>,
max_duration: Duration,
) -> Self::Create;
record_proof: RecordProof,
) -> Self::Proposal;
}
/// An oracle for when major synchronization work is being undertaken.