Reorganising the repository - external renames and moves (#4074)

* Adding first rough ouline of the repository structure

* Remove old CI stuff

* add title

* formatting fixes

* move node-exits job's script to scripts dir

* Move docs into subdir

* move to bin

* move maintainence scripts, configs and helpers into its own dir

* add .local to ignore

* move core->client

* start up 'test' area

* move test client

* move test runtime

* make test move compile

* Add dependencies rule enforcement.

* Fix indexing.

* Update docs to reflect latest changes

* Moving /srml->/paint

* update docs

* move client/sr-* -> primitives/

* clean old readme

* remove old broken code in rhd

* update lock

* Step 1.

* starting to untangle client

* Fix after merge.

* start splitting out client interfaces

* move children and blockchain interfaces

* Move trie and state-machine to primitives.

* Fix WASM builds.

* fixing broken imports

* more interface moves

* move backend and light to interfaces

* move CallExecutor

* move cli off client

* moving around more interfaces

* re-add consensus crates into the mix

* fix subkey path

* relieve client from executor

* starting to pull out client from grandpa

* move is_decendent_of out of client

* grandpa still depends on client directly

* lemme tests pass

* rename srml->paint

* Make it compile.

* rename interfaces->client-api

* Move keyring to primitives.

* fixup libp2p dep

* fix broken use

* allow dependency enforcement to fail

* move fork-tree

* Moving wasm-builder

* make env

* move build-script-utils

* fixup broken crate depdencies and names

* fix imports for authority discovery

* fix typo

* update cargo.lock

* fixing imports

* Fix paths and add missing crates

* re-add missing crates
This commit is contained in:
Benjamin Kampmann
2019-11-14 21:51:17 +01:00
committed by Bastian Köcher
parent becc3b0a4f
commit 60e5011c72
809 changed files with 7801 additions and 6464 deletions
@@ -0,0 +1,283 @@
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! A consensus proposer for "basic" chains which use the primitive inherent-data.
// FIXME #1021 move this into substrate-consensus-common
//
use std::{time, sync::Arc};
use client_api::{error, CallExecutor};
use client::Client as SubstrateClient;
use codec::Decode;
use consensus_common::{evaluation};
use inherents::InherentData;
use log::{error, info, debug, trace};
use primitives::{H256, Blake2Hasher, ExecutionContext};
use sr_primitives::{
traits::{
Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256
},
generic::BlockId,
};
use transaction_pool::txpool::{self, Pool as TransactionPool};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use block_builder::BlockBuilderApi;
/// Proposer factory.
pub struct ProposerFactory<C, A> where A: txpool::ChainApi {
/// The client instance.
pub client: Arc<C>,
/// The transaction pool.
pub transaction_pool: Arc<TransactionPool<A>>,
}
impl<B, E, Block, RA, A> consensus_common::Environment<Block> for
ProposerFactory<SubstrateClient<B, E, Block, RA>, A>
where
A: txpool::ChainApi<Block=Block>,
B: client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = error::Error>,
{
type Proposer = Proposer<Block, SubstrateClient<B, E, Block, RA>, A>;
type Error = error::Error;
fn init(
&mut self,
parent_header: &<Block as BlockT>::Header,
) -> Result<Self::Proposer, error::Error> {
let parent_hash = parent_header.hash();
let id = BlockId::hash(parent_hash);
info!("Starting consensus session on top of parent {:?}", parent_hash);
let proposer = Proposer {
client: self.client.clone(),
parent_hash,
parent_id: id,
parent_number: *parent_header.number(),
transaction_pool: self.transaction_pool.clone(),
now: Box::new(time::Instant::now),
};
Ok(proposer)
}
}
/// The proposer logic.
pub struct Proposer<Block: BlockT, C, A: txpool::ChainApi> {
client: Arc<C>,
parent_hash: <Block as BlockT>::Hash,
parent_id: BlockId<Block>,
parent_number: <<Block as BlockT>::Header as HeaderT>::Number,
transaction_pool: Arc<TransactionPool<A>>,
now: Box<dyn Fn() -> time::Instant>,
}
impl<B, E, Block, RA, A> consensus_common::Proposer<Block> for
Proposer<Block, SubstrateClient<B, E, Block, RA>, A>
where
A: txpool::ChainApi<Block=Block>,
B: client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = error::Error>,
{
type Create = futures::future::Ready<Result<Block, error::Error>>;
type Error = error::Error;
fn propose(
&mut self,
inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
max_duration: time::Duration,
) -> Self::Create {
// leave some time for evaluation and block finalization (33%)
let deadline = (self.now)() + max_duration - max_duration / 3;
futures::future::ready(self.propose_with(inherent_data, inherent_digests, deadline))
}
}
impl<Block, B, E, RA, A> Proposer<Block, SubstrateClient<B, E, Block, RA>, A> where
A: txpool::ChainApi<Block=Block>,
B: client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = error::Error>,
{
fn propose_with(
&self,
inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
deadline: time::Instant,
) -> Result<Block, error::Error> {
/// If the block is full we will attempt to push at most
/// this number of transactions before quitting for real.
/// It allows us to increase block utilization.
const MAX_SKIPPED_TRANSACTIONS: usize = 8;
let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests)?;
// We don't check the API versions any further here since the dispatch compatibility
// check should be enough.
for extrinsic in self.client.runtime_api()
.inherent_extrinsics_with_context(
&self.parent_id,
ExecutionContext::BlockConstruction,
inherent_data
)?
{
block_builder.push(extrinsic)?;
}
// proceed with transactions
let mut is_first = true;
let mut skipped = 0;
let mut unqueue_invalid = Vec::new();
let pending_iterator = self.transaction_pool.ready();
debug!("Attempting to push transactions from the pool.");
for pending in pending_iterator {
if (self.now)() > deadline {
debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing.");
break;
}
trace!("[{:?}] Pushing to the block.", pending.hash);
match block_builder::BlockBuilder::push(&mut block_builder, pending.data.clone()) {
Ok(()) => {
debug!("[{:?}] Pushed to the block.", pending.hash);
}
Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => {
if is_first {
debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash);
unqueue_invalid.push(pending.hash.clone());
} else if skipped < MAX_SKIPPED_TRANSACTIONS {
skipped += 1;
debug!(
"Block seems full, but will try {} more transactions before quitting.",
MAX_SKIPPED_TRANSACTIONS - skipped,
);
} else {
debug!("Block is full, proceed with proposing.");
break;
}
}
Err(e) => {
debug!("[{:?}] Invalid transaction: {}", pending.hash, e);
unqueue_invalid.push(pending.hash.clone());
}
}
is_first = false;
}
self.transaction_pool.remove_invalid(&unqueue_invalid);
let block = block_builder.bake()?;
info!("Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics: [{}]]",
block.header().number(),
<Block as BlockT>::Hash::from(block.header().hash()),
block.header().parent_hash(),
block.extrinsics()
.iter()
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
.collect::<Vec<_>>()
.join(", ")
);
telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing";
"number" => ?block.header().number(),
"hash" => ?<Block as BlockT>::Hash::from(block.header().hash()),
);
if Decode::decode(&mut block.encode().as_slice()).as_ref() != Ok(&block) {
error!("Failed to verify block encoding/decoding");
}
if let Err(err) = evaluation::evaluate_initial(&block, &self.parent_hash, self.parent_number) {
error!("Failed to evaluate authored block: {:?}", err);
}
Ok(block)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
use consensus_common::{Environment, Proposer};
use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring};
fn extrinsic(nonce: u64) -> Extrinsic {
Transfer {
amount: Default::default(),
nonce,
from: AccountKeyring::Alice.into(),
to: Default::default(),
}.into_signed_tx()
}
#[test]
fn should_cease_building_block_when_deadline_is_reached() {
// given
let client = Arc::new(test_client::new());
let chain_api = transaction_pool::FullChainApi::new(client.clone());
let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api));
futures::executor::block_on(
txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)], false)
).unwrap();
let mut proposer_factory = ProposerFactory {
client: client.clone(),
transaction_pool: txpool.clone(),
};
let mut proposer = proposer_factory.init(
&client.header(&BlockId::number(0)).unwrap().unwrap(),
).unwrap();
// when
let cell = RefCell::new(time::Instant::now());
proposer.now = Box::new(move || {
let new = *cell.borrow() + time::Duration::from_secs(2);
cell.replace(new)
});
let deadline = time::Duration::from_secs(3);
let block = futures::executor::block_on(proposer.propose(Default::default(), Default::default(), deadline))
.unwrap();
// then
// block should have some extrinsics although we have some more in the pool.
assert_eq!(block.extrinsics().len(), 1);
assert_eq!(txpool.ready().count(), 2);
}
}
@@ -0,0 +1,58 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Basic implementation of block-authoring logic.
//!
//! # Example
//!
//! ```
//! # use substrate_basic_authorship::ProposerFactory;
//! # use consensus_common::{Environment, Proposer};
//! # use sr_primitives::generic::BlockId;
//! # use std::{sync::Arc, time::Duration};
//! # use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring};
//! # use transaction_pool::txpool::{self, Pool as TransactionPool};
//! # let client = Arc::new(test_client::new());
//! # let chain_api = transaction_pool::FullChainApi::new(client.clone());
//! # let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api));
//! // The first step is to create a `ProposerFactory`.
//! let mut proposer_factory = ProposerFactory {
//! client: client.clone(),
//! transaction_pool: txpool.clone(),
//! };
//!
//! // From this factory, we create a `Proposer`.
//! let mut proposer = proposer_factory.init(
//! &client.header(&BlockId::number(0)).unwrap().unwrap(),
//! ).unwrap();
//!
//! // This `Proposer` allows us to create a block proposition.
//! // The proposer will grab transactions from the transaction pool, and put them into the block.
//! let future = proposer.propose(
//! Default::default(),
//! Default::default(),
//! Duration::from_secs(2)
//! );
//!
//! // We wait until the proposition is performed.
//! let block = futures::executor::block_on(future).unwrap();
//! println!("Generated block: {:?}", block);
//! ```
//!
mod basic_authorship;
pub use crate::basic_authorship::{ProposerFactory, Proposer};