mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-22 23:11:08 +00:00
Make everything compile and fix tests
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
hard_tabs=true
|
||||||
Generated
+4036
-2722
File diff suppressed because it is too large
Load Diff
+23
-12
@@ -6,33 +6,44 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
sr-primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-service = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
consensus-common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-api = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
cli = { package = "substrate-cli", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sc-service = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# Polkadot dependencies
|
# Polkadot dependencies
|
||||||
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# Cumulus dependencies
|
# Cumulus dependencies
|
||||||
cumulus-consensus = { path = "../consensus" }
|
cumulus-consensus = { path = "../consensus" }
|
||||||
cumulus-runtime = { path = "../runtime" }
|
cumulus-runtime = { path = "../runtime" }
|
||||||
|
|
||||||
# other deps
|
# Other dependencies
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
codec = { package = "parity-scale-codec", version = "1.0.6", features = [ "derive" ] }
|
codec = { package = "parity-scale-codec", version = "1.0.6", features = [ "derive" ] }
|
||||||
futures = "0.1.29"
|
futures = { version = "0.3.1", features = ["compat"] }
|
||||||
futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] }
|
|
||||||
parking_lot = "0.9"
|
parking_lot = "0.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
# Cumulus dependencies
|
||||||
test-runtime = { package = "cumulus-test-runtime", path = "../test/runtime" }
|
test-runtime = { package = "cumulus-test-runtime", path = "../test/runtime" }
|
||||||
test-client = { package = "cumulus-test-client", path = "../test/client" }
|
test-client = { package = "cumulus-test-client", path = "../test/client" }
|
||||||
|
|
||||||
|
# Substrate dependencies
|
||||||
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
polkadot-executor = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
|
# Polkadot dependencies
|
||||||
|
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
|
# Other dependencies
|
||||||
env_logger = "0.7.1"
|
env_logger = "0.7.1"
|
||||||
|
|||||||
+272
-196
@@ -18,34 +18,32 @@
|
|||||||
|
|
||||||
use cumulus_runtime::ParachainBlockData;
|
use cumulus_runtime::ParachainBlockData;
|
||||||
|
|
||||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT};
|
use sp_consensus::{
|
||||||
use consensus_common::{
|
BlockImport, BlockImportParams, BlockOrigin, Environment, Error as ConsensusError,
|
||||||
BlockImport, Environment, Proposer, ForkChoiceStrategy, BlockImportParams, BlockOrigin,
|
ForkChoiceStrategy, Proposal, Proposer, RecordProof,
|
||||||
Error as ConsensusError,
|
|
||||||
};
|
};
|
||||||
use inherents::InherentDataProviders;
|
use sp_inherents::InherentDataProviders;
|
||||||
use substrate_primitives::Blake2Hasher;
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
use polkadot_collator::{
|
use polkadot_collator::{
|
||||||
InvalidHead, ParachainContext, BuildParachainContext, Network as CollatorNetwork, VersionInfo,
|
BuildParachainContext, InvalidHead, Network as CollatorNetwork, ParachainContext,
|
||||||
TaskExecutor, PolkadotClient,
|
PolkadotClient,
|
||||||
};
|
};
|
||||||
use polkadot_primitives::{
|
use polkadot_primitives::{
|
||||||
Hash as PHash, Block as PBlock,
|
|
||||||
parachain::{
|
parachain::{
|
||||||
self, BlockData, Message, Id as ParaId, OutgoingMessages, Status as ParachainStatus,
|
self, BlockData, CollatorPair, Id as ParaId, Message, OutgoingMessages,
|
||||||
CollatorPair,
|
Status as ParachainStatus,
|
||||||
}
|
},
|
||||||
|
Block as PBlock, Hash as PHash,
|
||||||
};
|
};
|
||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
|
|
||||||
use log::{error, trace};
|
use log::{error, trace};
|
||||||
|
|
||||||
use futures03::{TryFutureExt, future};
|
use futures::{future, task::Spawn, Future, FutureExt, TryFutureExt};
|
||||||
use futures::{Future, future::IntoFuture};
|
|
||||||
|
|
||||||
use std::{sync::Arc, marker::PhantomData, time::Duration, fmt::Debug};
|
use std::{fmt::Debug, marker::PhantomData, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
@@ -95,17 +93,25 @@ impl<Block, PF, BI> Clone for Collator<Block, PF, BI> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Block, PF, BI> ParachainContext for Collator<Block, PF, BI>
|
impl<Block, PF, BI> ParachainContext for Collator<Block, PF, BI>
|
||||||
where
|
where
|
||||||
Block: BlockT,
|
Block: BlockT,
|
||||||
PF: Environment<Block> + 'static + Send,
|
PF: Environment<Block> + 'static + Send,
|
||||||
BI: BlockImport<Block, Error=ConsensusError> + Send + Sync + 'static,
|
PF::Proposer: Send,
|
||||||
|
BI: BlockImport<
|
||||||
|
Block,
|
||||||
|
Error = ConsensusError,
|
||||||
|
Transaction = <PF::Proposer as Proposer<Block>>::Transaction,
|
||||||
|
> + Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
{
|
{
|
||||||
type ProduceCandidate = Box<
|
type ProduceCandidate = Box<
|
||||||
dyn Future<Item=(BlockData, parachain::HeadData, OutgoingMessages), Error=InvalidHead>
|
dyn Future<Output = Result<(BlockData, parachain::HeadData, OutgoingMessages), InvalidHead>>
|
||||||
+ Send
|
+ Send
|
||||||
|
+ Unpin,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
|
fn produce_candidate<I: IntoIterator<Item = (ParaId, Message)>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_relay_chain_parent: PHash,
|
_relay_chain_parent: PHash,
|
||||||
status: ParachainStatus,
|
status: ParachainStatus,
|
||||||
@@ -117,124 +123,145 @@ impl<Block, PF, BI> ParachainContext for Collator<Block, PF, BI>
|
|||||||
let inherent_providers = self.inherent_data_providers.clone();
|
let inherent_providers = self.inherent_data_providers.clone();
|
||||||
let block_import = self.block_import.clone();
|
let block_import = self.block_import.clone();
|
||||||
|
|
||||||
let res = HeadData::<Block>::decode(&mut &status.head_data.0[..])
|
let res = future::ready(
|
||||||
.map_err(|e| {
|
HeadData::<Block>::decode(&mut &status.head_data.0[..]).map_err(|e| {
|
||||||
error!(target: "cumulus-collator", "Could not decode the head data: {:?}", e);
|
error!(target: "cumulus-collator", "Could not decode the head data: {:?}", e);
|
||||||
InvalidHead
|
InvalidHead
|
||||||
})
|
}),
|
||||||
.into_future()
|
)
|
||||||
.and_then(move |last_head| {
|
.and_then(move |last_head| {
|
||||||
let parent_state_root = *last_head.header.state_root();
|
let parent_state_root = *last_head.header.state_root();
|
||||||
|
|
||||||
factory.lock()
|
let proposer_inherent_data = factory
|
||||||
.init(&last_head.header)
|
.lock()
|
||||||
.map_err(|e| {
|
.init(&last_head.header)
|
||||||
error!(
|
.map_err(|e| {
|
||||||
target: "cumulus-collator",
|
error!(
|
||||||
"Could not create proposer: {:?}",
|
target: "cumulus-collator",
|
||||||
e,
|
"Could not create proposer: {:?}",
|
||||||
);
|
e,
|
||||||
InvalidHead
|
);
|
||||||
})
|
InvalidHead
|
||||||
.and_then(|mut proposer| {
|
})
|
||||||
let inherent_data = inherent_providers.create_inherent_data()
|
.and_then(|proposer| {
|
||||||
.map_err(|e| {
|
inherent_providers
|
||||||
error!(
|
.create_inherent_data()
|
||||||
target: "cumulus-collator",
|
|
||||||
"Failed to create inherent data: {:?}",
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
InvalidHead
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let future = proposer.propose(
|
|
||||||
inherent_data,
|
|
||||||
Default::default(),
|
|
||||||
//TODO: Fix this.
|
|
||||||
Duration::from_secs(6),
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!(
|
error!(
|
||||||
target: "cumulus-collator",
|
target: "cumulus-collator",
|
||||||
"Proposing failed: {:?}",
|
"Failed to create inherent data: {:?}",
|
||||||
e,
|
e,
|
||||||
);
|
);
|
||||||
InvalidHead
|
InvalidHead
|
||||||
})
|
})
|
||||||
.and_then(move |(block, proof)| {
|
.map(move |inherent_data| (proposer, inherent_data))
|
||||||
let res = match proof {
|
});
|
||||||
Some(proof) => {
|
|
||||||
let (header, extrinsics) = block.deconstruct();
|
|
||||||
|
|
||||||
// Create the parachain block data for the validators.
|
future::ready(proposer_inherent_data).and_then(move |(mut proposer, inherent_data)| {
|
||||||
Ok(
|
proposer
|
||||||
ParachainBlockData::<Block>::new(
|
.propose(
|
||||||
header,
|
inherent_data,
|
||||||
extrinsics,
|
Default::default(),
|
||||||
proof,
|
//TODO: Fix this.
|
||||||
parent_state_root,
|
Duration::from_secs(6),
|
||||||
)
|
RecordProof::Yes,
|
||||||
)
|
)
|
||||||
}
|
.map_err(|e| {
|
||||||
None => {
|
error!(
|
||||||
error!(
|
target: "cumulus-collator",
|
||||||
target: "cumulus-collator",
|
"Proposing failed: {:?}",
|
||||||
"Proposer did not return the requested proof.",
|
e,
|
||||||
);
|
);
|
||||||
Err(InvalidHead)
|
InvalidHead
|
||||||
}
|
})
|
||||||
};
|
.and_then(move |proposal| {
|
||||||
|
let Proposal {
|
||||||
|
block,
|
||||||
|
storage_changes,
|
||||||
|
proof,
|
||||||
|
} = proposal;
|
||||||
|
let res = match proof {
|
||||||
|
Some(proof) => {
|
||||||
|
let (header, extrinsics) = block.deconstruct();
|
||||||
|
|
||||||
future::ready(res)
|
// Create the parachain block data for the validators.
|
||||||
})
|
Ok((
|
||||||
.compat();
|
ParachainBlockData::<Block>::new(
|
||||||
|
header,
|
||||||
|
extrinsics,
|
||||||
|
proof.iter_nodes().collect(),
|
||||||
|
parent_state_root,
|
||||||
|
),
|
||||||
|
storage_changes,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error!(
|
||||||
|
target: "cumulus-collator",
|
||||||
|
"Proposer did not return the requested proof.",
|
||||||
|
);
|
||||||
|
Err(InvalidHead)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(future)
|
future::ready(res)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.flatten()
|
})
|
||||||
.and_then(move |b| {
|
.and_then(move |(b, storage_changes)| {
|
||||||
let block_import_params = BlockImportParams {
|
let block_import_params = BlockImportParams {
|
||||||
origin: BlockOrigin::Own,
|
origin: BlockOrigin::Own,
|
||||||
header: b.header().clone(),
|
header: b.header().clone(),
|
||||||
justification: None,
|
justification: None,
|
||||||
post_digests: vec![],
|
post_digests: vec![],
|
||||||
body: Some(b.extrinsics().to_vec()),
|
body: Some(b.extrinsics().to_vec()),
|
||||||
finalized: false,
|
finalized: false,
|
||||||
auxiliary: vec![], // block-weight is written in block import.
|
auxiliary: vec![], // block-weight is written in block import.
|
||||||
// TODO: block-import handles fork choice and this shouldn't even have the
|
// TODO: block-import handles fork choice and this shouldn't even have the
|
||||||
// option to specify one.
|
// option to specify one.
|
||||||
// https://github.com/paritytech/substrate/issues/3623
|
// https://github.com/paritytech/substrate/issues/3623
|
||||||
fork_choice: ForkChoiceStrategy::LongestChain,
|
fork_choice: ForkChoiceStrategy::LongestChain,
|
||||||
};
|
allow_missing_state: false,
|
||||||
|
import_existing: false,
|
||||||
|
storage_changes: Some(storage_changes),
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(err) = block_import.lock().import_block(
|
let res = if let Err(err) = block_import
|
||||||
block_import_params,
|
.lock()
|
||||||
Default::default(),
|
.import_block(block_import_params, Default::default())
|
||||||
) {
|
{
|
||||||
error!(
|
error!(
|
||||||
target: "cumulus-collator",
|
target: "cumulus-collator",
|
||||||
"Error importing build block (at {:?}): {:?}",
|
"Error importing build block (at {:?}): {:?}",
|
||||||
b.header().parent_hash(),
|
b.header().parent_hash(),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
Err(InvalidHead)
|
Err(InvalidHead)
|
||||||
} else {
|
} else {
|
||||||
Ok(b)
|
Ok(b)
|
||||||
}
|
};
|
||||||
})
|
|
||||||
.map(|b| {
|
|
||||||
let block_data = BlockData(b.encode());
|
|
||||||
let head_data = HeadData::<Block> { header: b.into_header() };
|
|
||||||
let messages = OutgoingMessages { outgoing_messages: Vec::new() };
|
|
||||||
|
|
||||||
(block_data, parachain::HeadData(head_data.encode()), messages)
|
future::ready(res)
|
||||||
})
|
})
|
||||||
.then(|r| {
|
.map_ok(|b| {
|
||||||
trace!(target: "cumulus-collator", "Produced candidate: {:?}", r);
|
let block_data = BlockData(b.encode());
|
||||||
r
|
let head_data = HeadData::<Block> {
|
||||||
});
|
header: b.into_header(),
|
||||||
|
};
|
||||||
|
let messages = OutgoingMessages {
|
||||||
|
outgoing_messages: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
block_data,
|
||||||
|
parachain::HeadData(head_data.encode()),
|
||||||
|
messages,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then(|r| {
|
||||||
|
trace!(target: "cumulus-collator", "Produced candidate: {:?}", r);
|
||||||
|
future::ready(r)
|
||||||
|
});
|
||||||
|
|
||||||
Box::new(res)
|
Box::new(res)
|
||||||
}
|
}
|
||||||
@@ -256,24 +283,44 @@ impl<Block, SP> CollatorBuilder<Block, SP> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block: BlockT, SP: SetupParachain<Block>> BuildParachainContext for CollatorBuilder<Block, SP> {
|
impl<Block: BlockT, SP: SetupParachain<Block>> BuildParachainContext for CollatorBuilder<Block, SP>
|
||||||
|
where
|
||||||
|
<SP::ProposerFactory as Environment<Block>>::Proposer: Send,
|
||||||
|
{
|
||||||
type ParachainContext = Collator<Block, SP::ProposerFactory, SP::BlockImport>;
|
type ParachainContext = Collator<Block, SP::ProposerFactory, SP::BlockImport>;
|
||||||
|
|
||||||
fn build<B, E>(
|
fn build<B, E, R, Spawner, Extrinsic>(
|
||||||
self,
|
self,
|
||||||
client: Arc<PolkadotClient<B, E>>,
|
client: Arc<PolkadotClient<B, E, R>>,
|
||||||
task_executor: TaskExecutor,
|
spawner: Spawner,
|
||||||
network: Arc<dyn CollatorNetwork>,
|
network: Arc<dyn CollatorNetwork>,
|
||||||
) -> Result<Self::ParachainContext, ()>
|
) -> Result<Self::ParachainContext, ()>
|
||||||
where
|
where
|
||||||
B: substrate_client::backend::Backend<PBlock, Blake2Hasher> + 'static,
|
PolkadotClient<B, E, R>: sp_api::ProvideRuntimeApi<PBlock>,
|
||||||
E: substrate_client::CallExecutor<PBlock, Blake2Hasher> + Clone + Send + Sync + 'static
|
<PolkadotClient<B, E, R> as sp_api::ProvideRuntimeApi<PBlock>>::Api:
|
||||||
|
polkadot_service::RuntimeApiCollection<Extrinsic>,
|
||||||
|
E: sc_client::CallExecutor<PBlock> + Clone + Send + Sync + 'static,
|
||||||
|
Spawner: Spawn + Clone + Send + Sync + 'static,
|
||||||
|
Extrinsic: codec::Codec + Send + Sync + 'static,
|
||||||
|
<<PolkadotClient<B, E, R> as sp_api::ProvideRuntimeApi<PBlock>>::Api as sp_api::ApiExt<
|
||||||
|
PBlock,
|
||||||
|
>>::StateBackend: sp_api::StateBackend<sp_core::Blake2Hasher>,
|
||||||
|
R: Send + Sync + 'static,
|
||||||
|
B: sc_client_api::Backend<PBlock> + 'static,
|
||||||
|
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||||
|
B::State: sp_api::StateBackend<sp_core::Blake2Hasher>,
|
||||||
{
|
{
|
||||||
let (proposer_factory, block_import, inherent_data_providers) = self.setup_parachain
|
let (proposer_factory, block_import, inherent_data_providers) = self
|
||||||
.setup_parachain(client, task_executor)
|
.setup_parachain
|
||||||
|
.setup_parachain(client, spawner)
|
||||||
.map_err(|e| error!("Error setting up the parachain: {}", e))?;
|
.map_err(|e| error!("Error setting up the parachain: {}", e))?;
|
||||||
|
|
||||||
Ok(Collator::new(proposer_factory, inherent_data_providers, network, block_import))
|
Ok(Collator::new(
|
||||||
|
proposer_factory,
|
||||||
|
inherent_data_providers,
|
||||||
|
network,
|
||||||
|
block_import,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,14 +329,32 @@ pub trait SetupParachain<Block: BlockT>: Send {
|
|||||||
/// The proposer factory of the parachain to build blocks.
|
/// The proposer factory of the parachain to build blocks.
|
||||||
type ProposerFactory: Environment<Block> + Send + 'static;
|
type ProposerFactory: Environment<Block> + Send + 'static;
|
||||||
/// The block import for importing the blocks build by the collator.
|
/// The block import for importing the blocks build by the collator.
|
||||||
type BlockImport: BlockImport<Block, Error=ConsensusError> + Send + Sync + 'static;
|
type BlockImport: BlockImport<
|
||||||
|
Block,
|
||||||
|
Error = ConsensusError,
|
||||||
|
Transaction = <<Self::ProposerFactory as Environment<Block>>::Proposer as Proposer<
|
||||||
|
Block,
|
||||||
|
>>::Transaction,
|
||||||
|
> + Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static;
|
||||||
|
|
||||||
/// Setup the parachain.
|
/// Setup the parachain.
|
||||||
fn setup_parachain<P: cumulus_consensus::PolkadotClient>(
|
fn setup_parachain<P, SP>(
|
||||||
self,
|
self,
|
||||||
polkadot_client: P,
|
polkadot_client: P,
|
||||||
task_executor: TaskExecutor,
|
spawner: SP,
|
||||||
) -> Result<(Self::ProposerFactory, Self::BlockImport, InherentDataProviders), String>;
|
) -> Result<
|
||||||
|
(
|
||||||
|
Self::ProposerFactory,
|
||||||
|
Self::BlockImport,
|
||||||
|
InherentDataProviders,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
P: cumulus_consensus::PolkadotClient,
|
||||||
|
SP: Spawn + Clone + Send + Sync + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a collator with the given proposer factory.
|
/// Run a collator with the given proposer factory.
|
||||||
@@ -298,16 +363,16 @@ pub fn run_collator<Block, SP, E>(
|
|||||||
para_id: ParaId,
|
para_id: ParaId,
|
||||||
exit: E,
|
exit: E,
|
||||||
key: Arc<CollatorPair>,
|
key: Arc<CollatorPair>,
|
||||||
version: VersionInfo,
|
configuration: polkadot_collator::Configuration,
|
||||||
) -> Result<(), cli::error::Error>
|
) -> Result<(), sc_cli::error::Error>
|
||||||
where
|
where
|
||||||
Block: BlockT,
|
Block: BlockT,
|
||||||
SP: SetupParachain<Block> + Send + 'static,
|
SP: SetupParachain<Block> + Send + 'static,
|
||||||
E: IntoFuture<Item=(), Error=()>,
|
<<SP as SetupParachain<Block>>::ProposerFactory as Environment<Block>>::Proposer: Send,
|
||||||
E::Future: Send + Clone + Sync + 'static,
|
E: Future<Output = ()> + Unpin + Send + Clone + Sync + 'static,
|
||||||
{
|
{
|
||||||
let builder = CollatorBuilder::new(setup_parachain);
|
let builder = CollatorBuilder::new(setup_parachain);
|
||||||
polkadot_collator::run_collator(builder, para_id, exit, key, version)
|
polkadot_collator::run_collator(builder, para_id, exit, key, configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -315,26 +380,31 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use polkadot_collator::{collate, RelayChainContext, PeerId, CollatorId, SignedStatement};
|
use polkadot_collator::{collate, CollatorId, PeerId, RelayChainContext, SignedStatement};
|
||||||
use polkadot_primitives::parachain::{ConsolidatedIngress, HeadData, FeeSchedule};
|
use polkadot_primitives::parachain::{ConsolidatedIngress, FeeSchedule, HeadData};
|
||||||
|
|
||||||
use keyring::Sr25519Keyring;
|
use sp_blockchain::Result as ClientResult;
|
||||||
use sr_primitives::{generic::BlockId, traits::{DigestFor, Header as HeaderT}};
|
use sp_inherents::InherentData;
|
||||||
use inherents::InherentData;
|
use sp_keyring::Sr25519Keyring;
|
||||||
use substrate_client::error::Result as ClientResult;
|
use sp_runtime::{
|
||||||
|
generic::BlockId,
|
||||||
|
traits::{DigestFor, Header as HeaderT},
|
||||||
|
};
|
||||||
|
use sp_state_machine::StorageProof;
|
||||||
use substrate_test_client::{NativeExecutor, WasmExecutionMethod::Interpreted};
|
use substrate_test_client::{NativeExecutor, WasmExecutionMethod::Interpreted};
|
||||||
|
|
||||||
|
use test_client::{
|
||||||
|
Client, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
|
||||||
|
};
|
||||||
use test_runtime::{Block, Header};
|
use test_runtime::{Block, Header};
|
||||||
use test_client::{Client, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt};
|
|
||||||
|
|
||||||
use futures03::future;
|
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Error;
|
struct Error;
|
||||||
|
|
||||||
impl From<consensus_common::Error> for Error {
|
impl From<sp_consensus::Error> for Error {
|
||||||
fn from(_: consensus_common::Error) -> Self {
|
fn from(_: sp_consensus::Error) -> Self {
|
||||||
unimplemented!("Not required in tests")
|
unimplemented!("Not required in tests")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,14 +424,15 @@ mod tests {
|
|||||||
|
|
||||||
impl Proposer<Block> for DummyProposer {
|
impl Proposer<Block> for DummyProposer {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Proposal = future::Ready<Result<(Block, Option<Vec<Vec<u8>>>), Error>>;
|
type Proposal = future::Ready<Result<Proposal<Block, Self::Transaction>, Error>>;
|
||||||
|
type Transaction = sc_client_api::TransactionFor<test_client::Backend, Block>;
|
||||||
|
|
||||||
fn propose(
|
fn propose(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: InherentData,
|
_: InherentData,
|
||||||
digest : DigestFor<Block>,
|
digest: DigestFor<Block>,
|
||||||
_: Duration,
|
_: Duration,
|
||||||
_: bool,
|
_: RecordProof,
|
||||||
) -> Self::Proposal {
|
) -> Self::Proposal {
|
||||||
let header = Header::new(
|
let header = Header::new(
|
||||||
1337,
|
1337,
|
||||||
@@ -371,22 +442,25 @@ mod tests {
|
|||||||
digest,
|
digest,
|
||||||
);
|
);
|
||||||
|
|
||||||
future::ready(Ok((Block::new(header, Vec::new()), Some(Default::default()))))
|
future::ready(Ok(Proposal {
|
||||||
|
block: Block::new(header, Vec::new()),
|
||||||
|
storage_changes: Default::default(),
|
||||||
|
proof: Some(StorageProof::empty()),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DummyCollatorNetwork;
|
struct DummyCollatorNetwork;
|
||||||
|
|
||||||
impl CollatorNetwork for DummyCollatorNetwork {
|
impl CollatorNetwork for DummyCollatorNetwork {
|
||||||
fn collator_id_to_peer_id(&self, _: CollatorId) ->
|
fn collator_id_to_peer_id(
|
||||||
Box<dyn Future<Item=Option<PeerId>, Error=()> + Send>
|
&self,
|
||||||
{
|
_: CollatorId,
|
||||||
|
) -> Box<dyn Future<Output = Option<PeerId>> + Send> {
|
||||||
unimplemented!("Not required in tests")
|
unimplemented!("Not required in tests")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checked_statements(&self, _: PHash) ->
|
fn checked_statements(&self, _: PHash) -> Box<dyn Stream<Item = SignedStatement>> {
|
||||||
Box<dyn Stream<Item=SignedStatement, Error=()>>
|
|
||||||
{
|
|
||||||
unimplemented!("Not required in tests")
|
unimplemented!("Not required in tests")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,10 +469,10 @@ mod tests {
|
|||||||
|
|
||||||
impl RelayChainContext for DummyRelayChainContext {
|
impl RelayChainContext for DummyRelayChainContext {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type FutureEgress = Result<ConsolidatedIngress, Self::Error>;
|
type FutureEgress = future::Ready<Result<ConsolidatedIngress, Error>>;
|
||||||
|
|
||||||
fn unrouted_egress(&self, _id: ParaId) -> Self::FutureEgress {
|
fn unrouted_egress(&self, _id: ParaId) -> Self::FutureEgress {
|
||||||
Ok(ConsolidatedIngress(Vec::new()))
|
future::ready(Ok(ConsolidatedIngress(Vec::new())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +481,7 @@ mod tests {
|
|||||||
|
|
||||||
impl cumulus_consensus::PolkadotClient for DummyPolkadotClient {
|
impl cumulus_consensus::PolkadotClient for DummyPolkadotClient {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Finalized = Box<dyn futures03::Stream<Item=Vec<u8>> + Send + Unpin>;
|
type Finalized = Box<dyn futures::Stream<Item = Vec<u8>> + Send + Unpin>;
|
||||||
|
|
||||||
fn finalized_heads(&self, _: ParaId) -> ClientResult<Self::Finalized> {
|
fn finalized_heads(&self, _: ParaId) -> ClientResult<Self::Finalized> {
|
||||||
unimplemented!("Not required in tests")
|
unimplemented!("Not required in tests")
|
||||||
@@ -417,7 +491,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_: &BlockId<PBlock>,
|
_: &BlockId<PBlock>,
|
||||||
_: ParaId,
|
_: ParaId,
|
||||||
) -> ClientResult<Option<Vec<u8>>>{
|
) -> ClientResult<Option<Vec<u8>>> {
|
||||||
unimplemented!("Not required in tests")
|
unimplemented!("Not required in tests")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,45 +502,45 @@ mod tests {
|
|||||||
type ProposerFactory = DummyFactory;
|
type ProposerFactory = DummyFactory;
|
||||||
type BlockImport = Client;
|
type BlockImport = Client;
|
||||||
|
|
||||||
fn setup_parachain<P: cumulus_consensus::PolkadotClient>(
|
fn setup_parachain<P, SP>(
|
||||||
self,
|
self,
|
||||||
_: P,
|
_: P,
|
||||||
_: TaskExecutor,
|
_: SP,
|
||||||
) -> Result<(Self::ProposerFactory, Self::BlockImport, InherentDataProviders), String> {
|
) -> Result<
|
||||||
Ok((DummyFactory, TestClientBuilder::new().build(), InherentDataProviders::default()))
|
(
|
||||||
}
|
Self::ProposerFactory,
|
||||||
}
|
Self::BlockImport,
|
||||||
|
InherentDataProviders,
|
||||||
type BoxFuture = Box<dyn Future<Item = (), Error = ()> + Send>;
|
),
|
||||||
|
String,
|
||||||
struct DummyFutureExecutor;
|
> {
|
||||||
|
Ok((
|
||||||
impl futures::future::Executor<BoxFuture>
|
DummyFactory,
|
||||||
for DummyFutureExecutor
|
TestClientBuilder::new().build(),
|
||||||
{
|
InherentDataProviders::default(),
|
||||||
fn execute(
|
))
|
||||||
&self,
|
|
||||||
_: BoxFuture,
|
|
||||||
) -> Result<(), futures::future::ExecuteError<BoxFuture>> {
|
|
||||||
unimplemented!("Not required in tests")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn collates_produces_a_block() {
|
fn collates_produces_a_block() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
let spawner = futures::executor::ThreadPool::new().unwrap();
|
||||||
|
|
||||||
let builder = CollatorBuilder::new(DummySetup);
|
let builder = CollatorBuilder::new(DummySetup);
|
||||||
let context = builder.build(
|
let context = builder
|
||||||
Arc::new(
|
.build::<_, _, polkadot_service::polkadot_runtime::RuntimeApi, _, _>(
|
||||||
substrate_test_client::TestClientBuilder::<_, _, ()>::default()
|
Arc::new(
|
||||||
.build_with_native_executor(
|
substrate_test_client::TestClientBuilder::<_, _, ()>::default()
|
||||||
Some(NativeExecutor::<polkadot_executor::Executor>::new(Interpreted, None)),
|
.build_with_native_executor(Some(NativeExecutor::<
|
||||||
).0
|
polkadot_service::PolkadotExecutor,
|
||||||
),
|
>::new(Interpreted, None)))
|
||||||
Arc::new(DummyFutureExecutor),
|
.0,
|
||||||
Arc::new(DummyCollatorNetwork),
|
),
|
||||||
).expect("Creates parachain context");
|
spawner,
|
||||||
|
Arc::new(DummyCollatorNetwork),
|
||||||
|
)
|
||||||
|
.expect("Creates parachain context");
|
||||||
|
|
||||||
let id = ParaId::from(100);
|
let id = ParaId::from(100);
|
||||||
let header = Header::new(
|
let header = Header::new(
|
||||||
@@ -491,7 +565,9 @@ mod tests {
|
|||||||
DummyRelayChainContext,
|
DummyRelayChainContext,
|
||||||
context,
|
context,
|
||||||
Arc::new(Sr25519Keyring::Alice.pair().into()),
|
Arc::new(Sr25519Keyring::Alice.pair().into()),
|
||||||
).wait().unwrap().0;
|
);
|
||||||
|
|
||||||
|
let collation = futures::executor::block_on(collation).unwrap().0;
|
||||||
|
|
||||||
let block_data = collation.pov.block_data;
|
let block_data = collation.pov.block_data;
|
||||||
|
|
||||||
|
|||||||
@@ -7,18 +7,22 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# substrate deps
|
# substrate deps
|
||||||
substrate-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-consensus-common = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-inherents = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-api = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# polkadot deps
|
# polkadot deps
|
||||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# other deps
|
# other deps
|
||||||
futures = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] }
|
futures = { version = "0.3.1", features = ["compat"] }
|
||||||
tokio = "0.1.22"
|
tokio = "0.1.22"
|
||||||
codec = { package = "parity-scale-codec", version = "1.0.5", features = [ "derive" ] }
|
codec = { package = "parity-scale-codec", version = "1.0.5", features = [ "derive" ] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|||||||
@@ -16,38 +16,37 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use substrate_primitives::{H256, Blake2Hasher};
|
use sc_client::Client;
|
||||||
|
use sc_client_api::{Backend, CallExecutor, TransactionFor};
|
||||||
use sr_primitives::{
|
use sp_api::ProvideRuntimeApi;
|
||||||
traits::{Block as BlockT, ProvideRuntimeApi, Header as HeaderT}, Justification,
|
use sp_block_builder::BlockBuilder as BlockBuilderApi;
|
||||||
|
use sp_blockchain::Result as ClientResult;
|
||||||
|
use sp_consensus::{
|
||||||
|
error::Error as ConsensusError,
|
||||||
|
import_queue::{BasicQueue, CacheKeyId, Verifier as VerifierT},
|
||||||
|
BlockImport, BlockImportParams, BlockOrigin, ForkChoiceStrategy,
|
||||||
|
};
|
||||||
|
use sp_inherents::InherentDataProviders;
|
||||||
|
use sp_runtime::{
|
||||||
generic::BlockId,
|
generic::BlockId,
|
||||||
|
traits::{Block as BlockT, Header as HeaderT},
|
||||||
|
Justification,
|
||||||
};
|
};
|
||||||
|
|
||||||
use substrate_client::{
|
|
||||||
block_builder::api::BlockBuilder as BlockBuilderApi, backend::Backend, CallExecutor, Client,
|
|
||||||
error::Result as ClientResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
use substrate_consensus_common::{
|
|
||||||
import_queue::{Verifier as VerifierT, BasicQueue, CacheKeyId}, BlockImportParams,
|
|
||||||
ForkChoiceStrategy, BlockOrigin, error::Error as ConsensusError, BlockImport,
|
|
||||||
};
|
|
||||||
|
|
||||||
use substrate_inherents::InherentDataProviders;
|
|
||||||
|
|
||||||
/// A verifier that just checks the inherents.
|
/// A verifier that just checks the inherents.
|
||||||
struct Verifier<B, E, Block: BlockT, RA> {
|
struct Verifier<B, E, Block: BlockT, RA> {
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client<B, E, Block, RA>>,
|
||||||
inherent_data_providers: InherentDataProviders,
|
inherent_data_providers: InherentDataProviders,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> VerifierT<Block> for Verifier<B, E, Block, RA> where
|
impl<B, E, Block, RA> VerifierT<Block> for Verifier<B, E, Block, RA>
|
||||||
Block: BlockT<Hash=H256>,
|
where
|
||||||
B: Backend<Block, Blake2Hasher> + 'static,
|
Block: BlockT,
|
||||||
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
|
B: Backend<Block> + 'static,
|
||||||
|
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
|
||||||
RA: Send + Sync,
|
RA: Send + Sync,
|
||||||
Client<B, E, Block, RA>: ProvideRuntimeApi + Send + Sync,
|
Client<B, E, Block, RA>: ProvideRuntimeApi<Block> + Send + Sync,
|
||||||
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api: BlockBuilderApi<Block>
|
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: BlockBuilderApi<Block>,
|
||||||
{
|
{
|
||||||
fn verify(
|
fn verify(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -55,33 +54,41 @@ impl<B, E, Block, RA> VerifierT<Block> for Verifier<B, E, Block, RA> where
|
|||||||
header: Block::Header,
|
header: Block::Header,
|
||||||
justification: Option<Justification>,
|
justification: Option<Justification>,
|
||||||
mut body: Option<Vec<Block::Extrinsic>>,
|
mut body: Option<Vec<Block::Extrinsic>>,
|
||||||
) -> Result<(BlockImportParams<Block>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
BlockImportParams<Block, ()>,
|
||||||
|
Option<Vec<(CacheKeyId, Vec<u8>)>>,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
> {
|
||||||
if let Some(inner_body) = body.take() {
|
if let Some(inner_body) = body.take() {
|
||||||
let inherent_data = self.inherent_data_providers
|
let inherent_data = self
|
||||||
|
.inherent_data_providers
|
||||||
.create_inherent_data()
|
.create_inherent_data()
|
||||||
.map_err(String::from)?;
|
.map_err(|e| e.into_string())?;
|
||||||
|
|
||||||
let block = Block::new(header.clone(), inner_body);
|
let block = Block::new(header.clone(), inner_body);
|
||||||
|
|
||||||
let inherent_res = self.client.runtime_api().check_inherents(
|
let inherent_res = self
|
||||||
&BlockId::Hash(*header.parent_hash()),
|
.client
|
||||||
block.clone(),
|
.runtime_api()
|
||||||
inherent_data,
|
.check_inherents(
|
||||||
).map_err(|e| format!("{:?}", e))?;
|
&BlockId::Hash(*header.parent_hash()),
|
||||||
|
block.clone(),
|
||||||
|
inherent_data,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
if !inherent_res.ok() {
|
if !inherent_res.ok() {
|
||||||
inherent_res
|
inherent_res.into_errors().try_for_each(|(i, e)| {
|
||||||
.into_errors()
|
Err(self.inherent_data_providers.error_to_string(&i, &e))
|
||||||
.try_for_each(|(i, e)| {
|
})?;
|
||||||
Err(self.inherent_data_providers.error_to_string(&i, &e))
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, inner_body) = block.deconstruct();
|
let (_, inner_body) = block.deconstruct();
|
||||||
body = Some(inner_body);
|
body = Some(inner_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let block_import_params = BlockImportParams {
|
let block_import_params = BlockImportParams {
|
||||||
origin,
|
origin,
|
||||||
header,
|
header,
|
||||||
@@ -91,6 +98,9 @@ impl<B, E, Block, RA> VerifierT<Block> for Verifier<B, E, Block, RA> where
|
|||||||
justification,
|
justification,
|
||||||
auxiliary: Vec::new(),
|
auxiliary: Vec::new(),
|
||||||
fork_choice: ForkChoiceStrategy::LongestChain,
|
fork_choice: ForkChoiceStrategy::LongestChain,
|
||||||
|
allow_missing_state: false,
|
||||||
|
import_existing: false,
|
||||||
|
storage_changes: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((block_import_params, None))
|
Ok((block_import_params, None))
|
||||||
@@ -98,22 +108,25 @@ impl<B, E, Block, RA> VerifierT<Block> for Verifier<B, E, Block, RA> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start an import queue for a Cumulus collator that does not uses any special authoring logic.
|
/// Start an import queue for a Cumulus collator that does not uses any special authoring logic.
|
||||||
pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA>(
|
pub fn import_queue<B, E, Block: BlockT, I, RA>(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client<B, E, Block, RA>>,
|
||||||
block_import: I,
|
block_import: I,
|
||||||
inherent_data_providers: InherentDataProviders,
|
inherent_data_providers: InherentDataProviders,
|
||||||
) -> ClientResult<BasicQueue<Block>>
|
) -> ClientResult<BasicQueue<Block, TransactionFor<B, Block>>>
|
||||||
where
|
where
|
||||||
B: Backend<Block, Blake2Hasher> + 'static,
|
B: Backend<Block> + 'static,
|
||||||
I: BlockImport<Block,Error=ConsensusError> + Send + Sync + 'static,
|
I: BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
|
||||||
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
|
+ Send
|
||||||
RA: Send + Sync + 'static,
|
+ Sync
|
||||||
Client<B, E, Block, RA>: ProvideRuntimeApi + Send + Sync + 'static,
|
+ 'static,
|
||||||
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api: BlockBuilderApi<Block>,
|
E: CallExecutor<Block> + Clone + Send + Sync + 'static,
|
||||||
|
RA: Send + Sync + 'static,
|
||||||
|
Client<B, E, Block, RA>: ProvideRuntimeApi<Block> + Send + Sync + 'static,
|
||||||
|
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: BlockBuilderApi<Block>,
|
||||||
{
|
{
|
||||||
let verifier = Verifier {
|
let verifier = Verifier {
|
||||||
client,
|
client,
|
||||||
inherent_data_providers
|
inherent_data_providers,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(BasicQueue::new(
|
Ok(BasicQueue::new(
|
||||||
|
|||||||
@@ -14,26 +14,29 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use substrate_client::{
|
use sc_client::{BlockchainEvents, Client};
|
||||||
backend::{Backend, Finalizer}, CallExecutor, Client, BlockchainEvents,
|
use sc_client_api::{
|
||||||
error::{Error as ClientError, Result as ClientResult},
|
backend::{Backend, Finalizer, StateBackend, StateBackendFor},
|
||||||
|
CallExecutor,
|
||||||
};
|
};
|
||||||
use substrate_primitives::{Blake2Hasher, H256};
|
use sp_api::ProvideRuntimeApi;
|
||||||
use sr_primitives::{
|
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||||
|
use sp_consensus::{Error as ConsensusError, SelectChain as SelectChainT};
|
||||||
|
use sp_runtime::{
|
||||||
generic::BlockId,
|
generic::BlockId,
|
||||||
traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi},
|
traits::{Block as BlockT, Header as HeaderT},
|
||||||
};
|
};
|
||||||
use substrate_consensus_common::{Error as ConsensusError, SelectChain as SelectChainT};
|
|
||||||
|
|
||||||
use polkadot_primitives::{
|
use polkadot_primitives::{
|
||||||
Hash as PHash, Block as PBlock, parachain::{Id as ParaId, ParachainHost},
|
parachain::{Id as ParaId, ParachainHost},
|
||||||
|
Block as PBlock, Hash as PHash,
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures::{Stream, StreamExt, TryStreamExt, future, Future, TryFutureExt, FutureExt};
|
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
|
use futures::{future, Future, FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
|
||||||
use std::{sync::Arc, marker::PhantomData};
|
use std::{marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
pub mod import_queue;
|
pub mod import_queue;
|
||||||
|
|
||||||
@@ -85,11 +88,14 @@ pub trait PolkadotClient: Clone + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns a future that follows the Polkadot relay chain for the given parachain.
|
/// Spawns a future that follows the Polkadot relay chain for the given parachain.
|
||||||
pub fn follow_polkadot<L, P>(para_id: ParaId, local: Arc<L>, polkadot: P)
|
pub fn follow_polkadot<L, P>(
|
||||||
-> ClientResult<impl Future<Output = ()> + Send + Unpin>
|
para_id: ParaId,
|
||||||
where
|
local: Arc<L>,
|
||||||
L: LocalClient + Send + Sync,
|
polkadot: P,
|
||||||
P: PolkadotClient,
|
) -> ClientResult<impl Future<Output = ()> + Send + Unpin>
|
||||||
|
where
|
||||||
|
L: LocalClient + Send + Sync,
|
||||||
|
P: PolkadotClient,
|
||||||
{
|
{
|
||||||
let finalized_heads = polkadot.finalized_heads(para_id)?;
|
let finalized_heads = polkadot.finalized_heads(para_id)?;
|
||||||
|
|
||||||
@@ -102,21 +108,25 @@ pub fn follow_polkadot<L, P>(para_id: ParaId, local: Arc<L>, polkadot: P)
|
|||||||
.map_err(|_| Error::InvalidHeadData)
|
.map_err(|_| Error::InvalidHeadData)
|
||||||
})
|
})
|
||||||
.try_for_each(move |p_head| {
|
.try_for_each(move |p_head| {
|
||||||
future::ready(local.finalize(p_head.hash()).map_err(Error::Client).map(|_| ()))
|
future::ready(
|
||||||
|
local
|
||||||
|
.finalize(p_head.hash())
|
||||||
|
.map_err(Error::Client)
|
||||||
|
.map(|_| ()),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(
|
Ok(follow_finalized
|
||||||
follow_finalized
|
.map_err(|e| warn!("Could not follow relay-chain: {:?}", e))
|
||||||
.map_err(|e| warn!("Could not follow relay-chain: {:?}", e))
|
.map(|_| ()))
|
||||||
.map(|_| ())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> LocalClient for Client<B, E, Block, RA> where
|
impl<B, E, Block, RA> LocalClient for Client<B, E, Block, RA>
|
||||||
B: Backend<Block, Blake2Hasher>,
|
where
|
||||||
E: CallExecutor<Block, Blake2Hasher>,
|
B: Backend<Block>,
|
||||||
Block: BlockT<Hash=H256>,
|
E: CallExecutor<Block>,
|
||||||
|
Block: BlockT,
|
||||||
{
|
{
|
||||||
type Block = Block;
|
type Block = Block;
|
||||||
|
|
||||||
@@ -126,30 +136,36 @@ impl<B, E, Block, RA> LocalClient for Client<B, E, Block, RA> where
|
|||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
ClientError::UnknownBlock(_) => Ok(false),
|
ClientError::UnknownBlock(_) => Ok(false),
|
||||||
_ => Err(e),
|
_ => Err(e),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, RA> PolkadotClient for Arc<Client<B, E, PBlock, RA>> where
|
impl<B, E, RA> PolkadotClient for Arc<Client<B, E, PBlock, RA>>
|
||||||
B: Backend<PBlock, Blake2Hasher> + Send + Sync + 'static,
|
where
|
||||||
E: CallExecutor<PBlock, Blake2Hasher> + Send + Sync + 'static,
|
B: Backend<PBlock> + Send + Sync + 'static,
|
||||||
Client<B, E, PBlock, RA>: ProvideRuntimeApi + Send + Sync + 'static,
|
E: CallExecutor<PBlock> + Send + Sync + 'static,
|
||||||
<Client<B, E, PBlock, RA> as ProvideRuntimeApi>::Api: ParachainHost<PBlock>,
|
Client<B, E, PBlock, RA>: ProvideRuntimeApi<PBlock> + Send + Sync + 'static,
|
||||||
|
<Client<B, E, PBlock, RA> as ProvideRuntimeApi<PBlock>>::Api:
|
||||||
|
ParachainHost<PBlock, Error = ClientError>,
|
||||||
|
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||||
|
StateBackendFor<B, PBlock>: StateBackend<sp_core::Blake2Hasher>,
|
||||||
{
|
{
|
||||||
type Error = ClientError;
|
type Error = ClientError;
|
||||||
|
|
||||||
type Finalized = Box<dyn Stream<Item=Vec<u8>> + Send + Unpin>;
|
type Finalized = Box<dyn Stream<Item = Vec<u8>> + Send + Unpin>;
|
||||||
|
|
||||||
fn finalized_heads(&self, para_id: ParaId) -> ClientResult<Self::Finalized> {
|
fn finalized_heads(&self, para_id: ParaId) -> ClientResult<Self::Finalized> {
|
||||||
let polkadot = self.clone();
|
let polkadot = self.clone();
|
||||||
|
|
||||||
let s = self.finality_notification_stream()
|
let s = self.finality_notification_stream().filter_map(move |n| {
|
||||||
.filter_map(move |n|
|
future::ready(
|
||||||
future::ready(
|
polkadot
|
||||||
polkadot.parachain_head_at(&BlockId::hash(n.hash), para_id).ok().and_then(|h| h),
|
.parachain_head_at(&BlockId::hash(n.hash), para_id)
|
||||||
),
|
.ok()
|
||||||
);
|
.and_then(|h| h),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
Ok(Box::new(s))
|
Ok(Box::new(s))
|
||||||
}
|
}
|
||||||
@@ -159,7 +175,9 @@ impl<B, E, RA> PolkadotClient for Arc<Client<B, E, PBlock, RA>> where
|
|||||||
at: &BlockId<PBlock>,
|
at: &BlockId<PBlock>,
|
||||||
para_id: ParaId,
|
para_id: ParaId,
|
||||||
) -> ClientResult<Option<Vec<u8>>> {
|
) -> ClientResult<Option<Vec<u8>>> {
|
||||||
self.runtime_api().parachain_status(at, para_id).map(|s| s.map(|s| s.head_data.0))
|
self.runtime_api()
|
||||||
|
.parachain_status(at, para_id)
|
||||||
|
.map(|s| s.map(|s| s.head_data.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,42 +219,41 @@ impl<Block, PC: Clone, SC: Clone> Clone for SelectChain<Block, PC, SC> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block, PC, SC> SelectChainT<Block> for SelectChain<Block, PC, SC> where
|
impl<Block, PC, SC> SelectChainT<Block> for SelectChain<Block, PC, SC>
|
||||||
Block: BlockT<Hash=H256>,
|
where
|
||||||
|
Block: BlockT,
|
||||||
PC: PolkadotClient + Clone + Send + Sync,
|
PC: PolkadotClient + Clone + Send + Sync,
|
||||||
PC::Error: ToString,
|
PC::Error: ToString,
|
||||||
SC: SelectChainT<PBlock>,
|
SC: SelectChainT<PBlock>,
|
||||||
{
|
{
|
||||||
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, ConsensusError> {
|
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, ConsensusError> {
|
||||||
let leaves = self.polkadot_select_chain.leaves()?;
|
let leaves = self.polkadot_select_chain.leaves()?;
|
||||||
leaves.into_iter()
|
leaves
|
||||||
.filter_map(|l|
|
.into_iter()
|
||||||
|
.filter_map(|l| {
|
||||||
self.polkadot_client
|
self.polkadot_client
|
||||||
.parachain_head_at(&BlockId::Hash(l), self.para_id)
|
.parachain_head_at(&BlockId::Hash(l), self.para_id)
|
||||||
.map(|h| h.and_then(|d| <<Block as BlockT>::Hash>::decode(&mut &d[..]).ok()))
|
.map(|h| h.and_then(|d| <<Block as BlockT>::Hash>::decode(&mut &d[..]).ok()))
|
||||||
.transpose()
|
.transpose()
|
||||||
)
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map_err(|e| ConsensusError::ChainLookup(e.to_string()))
|
.map_err(|e| ConsensusError::ChainLookup(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn best_chain(&self) -> Result<<Block as BlockT>::Header, ConsensusError> {
|
fn best_chain(&self) -> Result<<Block as BlockT>::Header, ConsensusError> {
|
||||||
let best_chain = self.polkadot_select_chain.best_chain()?;
|
let best_chain = self.polkadot_select_chain.best_chain()?;
|
||||||
let para_best_chain = self.polkadot_client
|
let para_best_chain = self
|
||||||
|
.polkadot_client
|
||||||
.parachain_head_at(&BlockId::Hash(best_chain.hash()), self.para_id)
|
.parachain_head_at(&BlockId::Hash(best_chain.hash()), self.para_id)
|
||||||
.map_err(|e| ConsensusError::ChainLookup(e.to_string()))?;
|
.map_err(|e| ConsensusError::ChainLookup(e.to_string()))?;
|
||||||
|
|
||||||
match para_best_chain {
|
match para_best_chain {
|
||||||
Some(best) => Decode::decode(&mut &best[..])
|
Some(best) => Decode::decode(&mut &best[..]).map_err(|e| {
|
||||||
.map_err(|e|
|
ConsensusError::ChainLookup(format!("Error decoding parachain head: {}", e.what()))
|
||||||
ConsensusError::ChainLookup(
|
}),
|
||||||
format!("Error decoding parachain head: {}", e.what()),
|
None => Err(ConsensusError::ChainLookup(
|
||||||
),
|
"Could not find parachain head for best relay chain!".into(),
|
||||||
),
|
)),
|
||||||
None => Err(
|
|
||||||
ConsensusError::ChainLookup(
|
|
||||||
"Could not find parachain head for best relay chain!".into()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# substrate deps
|
# substrate deps
|
||||||
substrate-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-consensus-common = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# polkadot deps
|
# polkadot deps
|
||||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
|||||||
+44
-38
@@ -18,14 +18,14 @@
|
|||||||
//!
|
//!
|
||||||
//! Contains message send between collators and logic to process them.
|
//! Contains message send between collators and logic to process them.
|
||||||
|
|
||||||
use substrate_client::error::{Error as ClientError};
|
use sp_blockchain::Error as ClientError;
|
||||||
use sr_primitives::traits::{Block as BlockT};
|
use sp_consensus::block_validation::{BlockAnnounceValidator, Validation};
|
||||||
use substrate_consensus_common::block_validation::{Validation, BlockAnnounceValidator};
|
use sp_runtime::traits::Block as BlockT;
|
||||||
|
|
||||||
|
use polkadot_network::gossip::{GossipMessage, GossipStatement};
|
||||||
use polkadot_primitives::parachain::ValidatorId;
|
use polkadot_primitives::parachain::ValidatorId;
|
||||||
use polkadot_statement_table::{SignedStatement, Statement};
|
use polkadot_statement_table::{SignedStatement, Statement};
|
||||||
use polkadot_validation::check_statement;
|
use polkadot_validation::check_statement;
|
||||||
use polkadot_network::gossip::{GossipStatement, GossipMessage};
|
|
||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
|
|
||||||
@@ -52,68 +52,74 @@ impl<B: BlockT> JustifiedBlockAnnounceValidator<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: BlockT> BlockAnnounceValidator<B> for JustifiedBlockAnnounceValidator<B> {
|
impl<B: BlockT> BlockAnnounceValidator<B> for JustifiedBlockAnnounceValidator<B> {
|
||||||
fn validate(&mut self, header: &B::Header, mut data: &[u8])
|
fn validate(
|
||||||
-> Result<Validation, Box<dyn std::error::Error + Send>>
|
&mut self,
|
||||||
{
|
header: &B::Header,
|
||||||
|
mut data: &[u8],
|
||||||
|
) -> Result<Validation, Box<dyn std::error::Error + Send>> {
|
||||||
// If no data is provided the announce is valid.
|
// If no data is provided the announce is valid.
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
return Ok(Validation::Success)
|
return Ok(Validation::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data is a gossip message.
|
// Check data is a gossip message.
|
||||||
let gossip_message = GossipMessage::decode(&mut data)
|
let gossip_message = GossipMessage::decode(&mut data).map_err(|_| {
|
||||||
.map_err(|_| Box::new(ClientError::BadJustification(
|
Box::new(ClientError::BadJustification(
|
||||||
"cannot decode block announced justification, must be a gossip message".to_string()
|
"cannot decode block announced justification, must be a gossip message".to_string(),
|
||||||
)) as Box<_>)?;
|
)) as Box<_>
|
||||||
|
})?;
|
||||||
|
|
||||||
// Check message is a gossip statement.
|
// Check message is a gossip statement.
|
||||||
let gossip_statement = match gossip_message {
|
let gossip_statement = match gossip_message {
|
||||||
GossipMessage::Statement(gossip_statement) => gossip_statement,
|
GossipMessage::Statement(gossip_statement) => gossip_statement,
|
||||||
_ => return Err(Box::new(ClientError::BadJustification(
|
_ => {
|
||||||
"block announced justification statement must be a gossip statement".to_string()
|
return Err(Box::new(ClientError::BadJustification(
|
||||||
)) as Box<_>)
|
"block announced justification statement must be a gossip statement"
|
||||||
|
.to_string(),
|
||||||
|
)) as Box<_>)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let GossipStatement {
|
let GossipStatement {
|
||||||
relay_chain_leaf,
|
relay_chain_leaf,
|
||||||
signed_statement: SignedStatement {
|
signed_statement: SignedStatement {
|
||||||
statement,
|
statement,
|
||||||
signature,
|
signature,
|
||||||
sender,
|
sender,
|
||||||
}
|
},
|
||||||
} = gossip_statement;
|
} = gossip_statement;
|
||||||
|
|
||||||
// Check that the signer is a legit validator.
|
// Check that the signer is a legit validator.
|
||||||
let signer = self.authorities.get(sender as usize)
|
let signer = self.authorities.get(sender as usize).ok_or_else(|| {
|
||||||
.ok_or_else(|| Box::new(ClientError::BadJustification(
|
Box::new(ClientError::BadJustification(
|
||||||
"block accounced justification signer is a validator index out of bound".to_string()
|
"block accounced justification signer is a validator index out of bound"
|
||||||
)) as Box<_>)?;
|
.to_string(),
|
||||||
|
)) as Box<_>
|
||||||
|
})?;
|
||||||
|
|
||||||
// Check statement is correctly signed.
|
// Check statement is correctly signed.
|
||||||
if !check_statement(
|
if !check_statement(&statement, &signature, signer.clone(), &relay_chain_leaf) {
|
||||||
&statement,
|
|
||||||
&signature,
|
|
||||||
signer.clone(),
|
|
||||||
&relay_chain_leaf,
|
|
||||||
) {
|
|
||||||
return Err(Box::new(ClientError::BadJustification(
|
return Err(Box::new(ClientError::BadJustification(
|
||||||
"block announced justification signature is invalid".to_string()
|
"block announced justification signature is invalid".to_string(),
|
||||||
)) as Box<_>)
|
)) as Box<_>);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check statement is a candidate statement.
|
// Check statement is a candidate statement.
|
||||||
let candidate_receipt = match statement {
|
let candidate_receipt = match statement {
|
||||||
Statement::Candidate(candidate_receipt) => candidate_receipt,
|
Statement::Candidate(candidate_receipt) => candidate_receipt,
|
||||||
_ => return Err(Box::new(ClientError::BadJustification(
|
_ => {
|
||||||
"block announced justification statement must be a candidate statement".to_string()
|
return Err(Box::new(ClientError::BadJustification(
|
||||||
)) as Box<_>)
|
"block announced justification statement must be a candidate statement"
|
||||||
|
.to_string(),
|
||||||
|
)) as Box<_>)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check the header in the candidate_receipt match header given header.
|
// Check the header in the candidate_receipt match header given header.
|
||||||
if header.encode() != candidate_receipt.head_data.0 {
|
if header.encode() != candidate_receipt.head_data.0 {
|
||||||
return Err(Box::new(ClientError::BadJustification(
|
return Err(Box::new(ClientError::BadJustification(
|
||||||
"block announced header does not match the one justified".to_string()
|
"block announced header does not match the one justified".to_string(),
|
||||||
)) as Box<_>)
|
)) as Box<_>);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Validation::Success)
|
Ok(Validation::Success)
|
||||||
|
|||||||
+18
-17
@@ -7,40 +7,41 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# Other dependencies
|
# Other dependencies
|
||||||
codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = [ "derive" ] }
|
codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = [ "derive" ] }
|
||||||
memory-db = { version = "0.15.2", default-features = false }
|
memory-db = { version = "0.18.0", default-features = false }
|
||||||
hash-db = { version = "0.15.2", default-features = false }
|
hash-db = { version = "0.15.2", default-features = false }
|
||||||
trie-db = { version = "0.15.2", default-features = false }
|
trie-db = { version = "0.18.0", default-features = false }
|
||||||
hashbrown = "0.6.1"
|
hashbrown = "0.6.1"
|
||||||
|
|
||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
runtime-primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
rio = { package = "sr-io", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
executive = { package = "srml-executive", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
substrate-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# Polkadot dependencies
|
# Polkadot dependencies
|
||||||
parachain = { package = "polkadot-parachain", git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch", default-features = false, features = [ "wasm-api" ] }
|
parachain = { package = "polkadot-parachain", git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch", default-features = false, features = [ "wasm-api" ] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
executor = { package = "substrate-executor", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
consensus-common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
test-client = { package = "cumulus-test-client", path = "../test/client" }
|
test-client = { package = "cumulus-test-client", path = "../test/client" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [
|
std = [
|
||||||
"codec/std",
|
"codec/std",
|
||||||
"rstd/std",
|
"sp-std/std",
|
||||||
"rio/std",
|
"sp-io/std",
|
||||||
"runtime-primitives/std",
|
"sp-runtime/std",
|
||||||
"primitives/std",
|
"sp-core/std",
|
||||||
"executive/std",
|
"frame-executive/std",
|
||||||
"memory-db/std",
|
"memory-db/std",
|
||||||
"hash-db/std",
|
"hash-db/std",
|
||||||
"trie-db/std",
|
"trie-db/std",
|
||||||
"substrate-trie/std",
|
"sp-trie/std",
|
||||||
"parachain/std",
|
"parachain/std",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -16,15 +16,14 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
use sp_runtime::traits::Block as BlockT;
|
||||||
///! The Cumulus runtime to make a runtime a parachain.
|
///! The Cumulus runtime to make a runtime a parachain.
|
||||||
|
use sp_std::vec::Vec;
|
||||||
use rstd::vec::Vec;
|
|
||||||
use codec::{Encode, Decode};
|
|
||||||
use runtime_primitives::traits::Block as BlockT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use rstd::slice;
|
pub use sp_std::slice;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod validate_block;
|
pub mod validate_block;
|
||||||
|
|||||||
@@ -17,23 +17,38 @@
|
|||||||
//! The actual implementation of the validate block functionality.
|
//! The actual implementation of the validate block functionality.
|
||||||
|
|
||||||
use crate::WitnessData;
|
use crate::WitnessData;
|
||||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
use frame_executive::ExecuteBlock;
|
||||||
use executive::ExecuteBlock;
|
use sp_runtime::traits::{Block as BlockT, HasherFor, Header as HeaderT};
|
||||||
use primitives::{Blake2Hasher, H256};
|
|
||||||
|
|
||||||
use substrate_trie::{MemoryDB, read_trie_value, delta_trie_root, Layout};
|
use sp_trie::{delta_trie_root, read_trie_value, Layout, MemoryDB};
|
||||||
|
|
||||||
use rstd::{slice, ptr, cmp, vec::Vec, boxed::Box, mem};
|
use sp_std::{boxed::Box, vec::Vec};
|
||||||
|
|
||||||
use hash_db::{HashDB, EMPTY_PREFIX};
|
use hash_db::{HashDB, EMPTY_PREFIX};
|
||||||
|
|
||||||
|
use trie_db::{Trie, TrieDB};
|
||||||
|
|
||||||
use parachain::{ValidationParams, ValidationResult};
|
use parachain::{ValidationParams, ValidationResult};
|
||||||
|
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
|
||||||
|
/// Stores the global [`Storage`] instance.
|
||||||
|
///
|
||||||
|
/// As wasm is always executed with one thread, this global varibale is safe!
|
||||||
static mut STORAGE: Option<Box<dyn Storage>> = None;
|
static mut STORAGE: Option<Box<dyn Storage>> = None;
|
||||||
/// The message to use as expect message while accessing the `STORAGE`.
|
|
||||||
const STORAGE_SET_EXPECT: &str =
|
/// Returns a mutable reference to the [`Storage`] implementation.
|
||||||
"`STORAGE` needs to be set before calling this function.";
|
///
|
||||||
const STORAGE_ROOT_LEN: usize = 32;
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the [`STORAGE`] is not initialized.
|
||||||
|
fn storage() -> &'static mut dyn Storage {
|
||||||
|
unsafe {
|
||||||
|
&mut **STORAGE
|
||||||
|
.as_mut()
|
||||||
|
.expect("`STORAGE` needs to be set before calling this function.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Abstract the storage into a trait without `Block` generic.
|
/// Abstract the storage into a trait without `Block` generic.
|
||||||
trait Storage {
|
trait Storage {
|
||||||
@@ -47,16 +62,17 @@ trait Storage {
|
|||||||
fn remove(&mut self, key: &[u8]);
|
fn remove(&mut self, key: &[u8]);
|
||||||
|
|
||||||
/// Calculate the storage root.
|
/// Calculate the storage root.
|
||||||
fn storage_root(&mut self) -> [u8; STORAGE_ROOT_LEN];
|
///
|
||||||
|
/// Returns the SCALE encoded hash.
|
||||||
|
fn storage_root(&mut self) -> Vec<u8>;
|
||||||
|
|
||||||
|
/// Clear all keys that start with the given prefix.
|
||||||
|
fn clear_prefix(&mut self, prefix: &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate a given parachain block on a validator.
|
/// Validate a given parachain block on a validator.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn validate_block<B: BlockT<Hash = H256>, E: ExecuteBlock<B>>(
|
pub fn validate_block<B: BlockT, E: ExecuteBlock<B>>(params: ValidationParams) -> ValidationResult {
|
||||||
params: ValidationParams,
|
|
||||||
) -> ValidationResult {
|
|
||||||
use codec::{Decode, Encode};
|
|
||||||
|
|
||||||
let block_data = crate::ParachainBlockData::<B>::decode(&mut ¶ms.block_data[..])
|
let block_data = crate::ParachainBlockData::<B>::decode(&mut ¶ms.block_data[..])
|
||||||
.expect("Invalid parachain block data");
|
.expect("Invalid parachain block data");
|
||||||
|
|
||||||
@@ -66,23 +82,28 @@ pub fn validate_block<B: BlockT<Hash = H256>, E: ExecuteBlock<B>>(
|
|||||||
|
|
||||||
// TODO: Add `PolkadotInherent`.
|
// TODO: Add `PolkadotInherent`.
|
||||||
let block = B::new(block_data.header, block_data.extrinsics);
|
let block = B::new(block_data.header, block_data.extrinsics);
|
||||||
assert!(parent_head.hash() == *block.header().parent_hash(), "Invalid parent hash");
|
assert!(
|
||||||
|
parent_head.hash() == *block.header().parent_hash(),
|
||||||
|
"Invalid parent hash"
|
||||||
|
);
|
||||||
|
|
||||||
let storage = WitnessStorage::<B>::new(
|
let storage = WitnessStorage::<B>::new(
|
||||||
block_data.witness_data,
|
block_data.witness_data,
|
||||||
block_data.witness_data_storage_root,
|
block_data.witness_data_storage_root,
|
||||||
).expect("Witness data and storage root always match; qed");
|
)
|
||||||
|
.expect("Witness data and storage root always match; qed");
|
||||||
|
|
||||||
let _guard = unsafe {
|
let _guard = unsafe {
|
||||||
STORAGE = Some(Box::new(storage));
|
STORAGE = Some(Box::new(storage));
|
||||||
(
|
(
|
||||||
// Replace storage calls with our own implementations
|
// Replace storage calls with our own implementations
|
||||||
rio::ext_get_allocated_storage.replace_implementation(ext_get_allocated_storage),
|
sp_io::storage::host_read.replace_implementation(host_storage_read),
|
||||||
rio::ext_get_storage_into.replace_implementation(ext_get_storage_into),
|
sp_io::storage::host_set.replace_implementation(host_storage_set),
|
||||||
rio::ext_set_storage.replace_implementation(ext_set_storage),
|
sp_io::storage::host_get.replace_implementation(host_storage_get),
|
||||||
rio::ext_exists_storage.replace_implementation(ext_exists_storage),
|
sp_io::storage::host_exists.replace_implementation(host_storage_exists),
|
||||||
rio::ext_clear_storage.replace_implementation(ext_clear_storage),
|
sp_io::storage::host_clear.replace_implementation(host_storage_clear),
|
||||||
rio::ext_storage_root.replace_implementation(ext_storage_root),
|
sp_io::storage::host_root.replace_implementation(host_storage_root),
|
||||||
|
sp_io::storage::host_clear_prefix.replace_implementation(host_clear_prefix),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,24 +115,23 @@ pub fn validate_block<B: BlockT<Hash = H256>, E: ExecuteBlock<B>>(
|
|||||||
/// The storage implementation used when validating a block that is using the
|
/// The storage implementation used when validating a block that is using the
|
||||||
/// witness data as source.
|
/// witness data as source.
|
||||||
struct WitnessStorage<B: BlockT> {
|
struct WitnessStorage<B: BlockT> {
|
||||||
witness_data: MemoryDB<Blake2Hasher>,
|
witness_data: MemoryDB<HasherFor<B>>,
|
||||||
overlay: hashbrown::HashMap<Vec<u8>, Option<Vec<u8>>>,
|
overlay: hashbrown::HashMap<Vec<u8>, Option<Vec<u8>>>,
|
||||||
storage_root: B::Hash,
|
storage_root: B::Hash,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: BlockT<Hash = H256>> WitnessStorage<B> {
|
impl<B: BlockT> WitnessStorage<B> {
|
||||||
/// Initialize from the given witness data and storage root.
|
/// Initialize from the given witness data and storage root.
|
||||||
///
|
///
|
||||||
/// Returns an error if given storage root was not found in the witness data.
|
/// Returns an error if given storage root was not found in the witness data.
|
||||||
fn new(
|
fn new(data: WitnessData, storage_root: B::Hash) -> Result<Self, &'static str> {
|
||||||
data: WitnessData,
|
|
||||||
storage_root: B::Hash,
|
|
||||||
) -> Result<Self, &'static str> {
|
|
||||||
let mut db = MemoryDB::default();
|
let mut db = MemoryDB::default();
|
||||||
data.into_iter().for_each(|i| { db.insert(EMPTY_PREFIX, &i); });
|
data.into_iter().for_each(|i| {
|
||||||
|
db.insert(EMPTY_PREFIX, &i);
|
||||||
|
});
|
||||||
|
|
||||||
if !db.contains(&storage_root, EMPTY_PREFIX) {
|
if !HashDB::contains(&db, &storage_root, EMPTY_PREFIX) {
|
||||||
return Err("Witness data does not contain given storage root.")
|
return Err("Witness data does not contain given storage root.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -122,15 +142,36 @@ impl<B: BlockT<Hash = H256>> WitnessStorage<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: BlockT<Hash = H256>> Storage for WitnessStorage<B> {
|
/// TODO: `TrieError` should implement `Debug` on `no_std`
|
||||||
|
fn unwrap_trie_error<R, T, E>(result: Result<R, Box<trie_db::TrieError<T, E>>>) -> R {
|
||||||
|
match result {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(error) => match *error {
|
||||||
|
trie_db::TrieError::InvalidStateRoot(_) => panic!("trie_db: Invalid state root"),
|
||||||
|
trie_db::TrieError::IncompleteDatabase(_) => panic!("trie_db: IncompleteDatabase"),
|
||||||
|
trie_db::TrieError::DecoderError(_, _) => panic!("trie_db: DecodeError"),
|
||||||
|
trie_db::TrieError::InvalidHash(_, _) => panic!("trie_db: InvalidHash"),
|
||||||
|
trie_db::TrieError::ValueAtIncompleteKey(_, _) => {
|
||||||
|
panic!("trie_db: ValueAtIncompleteKey")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: BlockT> Storage for WitnessStorage<B> {
|
||||||
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
|
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||||
self.overlay.get(key).cloned().or_else(|| {
|
self.overlay
|
||||||
read_trie_value::<Layout<Blake2Hasher>, _>(
|
.get(key)
|
||||||
&self.witness_data,
|
.cloned()
|
||||||
&self.storage_root,
|
.or_else(|| {
|
||||||
key,
|
read_trie_value::<Layout<HasherFor<B>>, _>(
|
||||||
).ok()
|
&self.witness_data,
|
||||||
}).unwrap_or(None)
|
&self.storage_root,
|
||||||
|
key,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, key: &[u8], value: &[u8]) {
|
fn insert(&mut self, key: &[u8], value: &[u8]) {
|
||||||
@@ -141,98 +182,77 @@ impl<B: BlockT<Hash = H256>> Storage for WitnessStorage<B> {
|
|||||||
self.overlay.insert(key.to_vec(), None);
|
self.overlay.insert(key.to_vec(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage_root(&mut self) -> [u8; STORAGE_ROOT_LEN] {
|
fn storage_root(&mut self) -> Vec<u8> {
|
||||||
let root = match delta_trie_root::<Layout<Blake2Hasher>, _, _, _, _>(
|
let root = unwrap_trie_error(delta_trie_root::<Layout<HasherFor<B>>, _, _, _, _>(
|
||||||
&mut self.witness_data,
|
&mut self.witness_data,
|
||||||
self.storage_root.clone(),
|
self.storage_root.clone(),
|
||||||
self.overlay.drain(),
|
self.overlay.drain(),
|
||||||
) {
|
));
|
||||||
Ok(root) => root,
|
|
||||||
Err(e) => match *e {
|
root.encode()
|
||||||
trie_db::TrieError::InvalidStateRoot(_) => panic!("Invalid state root"),
|
}
|
||||||
trie_db::TrieError::IncompleteDatabase(_) => panic!("IncompleteDatabase"),
|
|
||||||
trie_db::TrieError::DecoderError(_, _) => panic!("DecodeError"),
|
fn clear_prefix(&mut self, prefix: &[u8]) {
|
||||||
|
self.overlay.iter_mut().for_each(|(k, v)| {
|
||||||
|
if k.starts_with(prefix) {
|
||||||
|
*v = None;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let trie = match TrieDB::<Layout<HasherFor<B>>>::new(&self.witness_data, &self.storage_root)
|
||||||
|
{
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => panic!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.into()
|
let mut iter = unwrap_trie_error(trie.iter());
|
||||||
}
|
unwrap_trie_error(iter.seek(prefix));
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn ext_get_allocated_storage(
|
for x in iter {
|
||||||
key_data: *const u8,
|
let (key, _) = unwrap_trie_error(x);
|
||||||
key_len: u32,
|
|
||||||
written_out: *mut u32,
|
if !key.starts_with(prefix) {
|
||||||
) -> *mut u8 {
|
break;
|
||||||
let key = slice::from_raw_parts(key_data, key_len as usize);
|
}
|
||||||
match STORAGE.as_mut().expect(STORAGE_SET_EXPECT).get(key) {
|
|
||||||
Some(value) => {
|
self.overlay.insert(key, None);
|
||||||
let mut out_value: Vec<_> = value.clone();
|
|
||||||
*written_out = out_value.len() as u32;
|
|
||||||
let ptr = out_value.as_mut_ptr();
|
|
||||||
mem::forget(out_value);
|
|
||||||
ptr
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
*written_out = u32::max_value();
|
|
||||||
ptr::null_mut()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ext_set_storage(
|
fn host_storage_read(key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option<u32> {
|
||||||
key_data: *const u8,
|
match storage().get(key) {
|
||||||
key_len: u32,
|
|
||||||
value_data: *const u8,
|
|
||||||
value_len: u32,
|
|
||||||
) {
|
|
||||||
let key = slice::from_raw_parts(key_data, key_len as usize);
|
|
||||||
let value = slice::from_raw_parts(value_data, value_len as usize);
|
|
||||||
|
|
||||||
STORAGE.as_mut().expect(STORAGE_SET_EXPECT).insert(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn ext_get_storage_into(
|
|
||||||
key_data: *const u8,
|
|
||||||
key_len: u32,
|
|
||||||
value_data: *mut u8,
|
|
||||||
value_len: u32,
|
|
||||||
value_offset: u32,
|
|
||||||
) -> u32 {
|
|
||||||
let key = slice::from_raw_parts(key_data, key_len as usize);
|
|
||||||
let out_value = slice::from_raw_parts_mut(value_data, value_len as usize);
|
|
||||||
|
|
||||||
match STORAGE.as_mut().expect(STORAGE_SET_EXPECT).get(key) {
|
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
let value = &value[value_offset as usize..];
|
let value_offset = value_offset as usize;
|
||||||
let len = cmp::min(value_len as usize, value.len());
|
let data = &value[value_offset.min(value.len())..];
|
||||||
out_value[..len].copy_from_slice(&value[..len]);
|
let written = sp_std::cmp::min(data.len(), value_out.len());
|
||||||
len as u32
|
value_out[..written].copy_from_slice(&data[..written]);
|
||||||
},
|
Some(value.len() as u32)
|
||||||
None => {
|
|
||||||
u32::max_value()
|
|
||||||
}
|
}
|
||||||
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 {
|
fn host_storage_set(key: &[u8], value: &[u8]) {
|
||||||
let key = slice::from_raw_parts(key_data, key_len as usize);
|
storage().insert(key, value);
|
||||||
|
|
||||||
if STORAGE.as_mut().expect(STORAGE_SET_EXPECT).get(key).is_some() {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ext_clear_storage(key_data: *const u8, key_len: u32) {
|
fn host_storage_get(key: &[u8]) -> Option<Vec<u8>> {
|
||||||
let key = slice::from_raw_parts(key_data, key_len as usize);
|
storage().get(key).clone()
|
||||||
|
|
||||||
STORAGE.as_mut().expect(STORAGE_SET_EXPECT).remove(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ext_storage_root(result: *mut u8) {
|
fn host_storage_exists(key: &[u8]) -> bool {
|
||||||
let res = STORAGE.as_mut().expect(STORAGE_SET_EXPECT).storage_root();
|
storage().get(key).is_some()
|
||||||
let result = slice::from_raw_parts_mut(result, STORAGE_ROOT_LEN);
|
}
|
||||||
result.copy_from_slice(&res);
|
|
||||||
|
fn host_storage_clear(key: &[u8]) {
|
||||||
|
storage().remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn host_storage_root() -> Vec<u8> {
|
||||||
|
storage().storage_root()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn host_clear_prefix(prefix: &[u8]) {
|
||||||
|
storage().clear_prefix(prefix)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
//! A module that enables a runtime to work as parachain.
|
//! A module that enables a runtime to work as parachain.
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod implementation;
|
pub mod implementation;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -60,20 +60,16 @@ macro_rules! register_validate_block_impl {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe fn validate_block(
|
unsafe fn validate_block(arguments: *const u8, arguments_len: usize) -> u64 {
|
||||||
arguments: *const u8,
|
let params =
|
||||||
arguments_len: usize,
|
$crate::validate_block::parachain::load_params(arguments, arguments_len);
|
||||||
) -> u64 {
|
|
||||||
let params = $crate::validate_block::parachain::wasm_api::load_params(
|
|
||||||
arguments,
|
|
||||||
arguments_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
let res = $crate::validate_block::implementation::validate_block::<
|
let res = $crate::validate_block::implementation::validate_block::<
|
||||||
$block, $block_executor
|
$block,
|
||||||
|
$block_executor,
|
||||||
>(params);
|
>(params);
|
||||||
|
|
||||||
$crate::validate_block::parachain::wasm_api::write_result(res)
|
$crate::validate_block::parachain::write_result(&res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,18 +16,22 @@
|
|||||||
|
|
||||||
use crate::{ParachainBlockData, WitnessData};
|
use crate::{ParachainBlockData, WitnessData};
|
||||||
|
|
||||||
use rio::TestExternalities;
|
|
||||||
use keyring::AccountKeyring;
|
|
||||||
use runtime_primitives::{generic::BlockId, traits::{Block as BlockT, Header as HeaderT}};
|
|
||||||
use executor::{call_in_wasm, error::Result, WasmExecutionMethod};
|
|
||||||
use test_client::{
|
|
||||||
TestClientBuilder, TestClientBuilderExt, DefaultTestClientBuilderExt, Client, LongestChain,
|
|
||||||
runtime::{Block, Transfer, Hash, WASM_BINARY, Header}
|
|
||||||
};
|
|
||||||
use consensus_common::SelectChain;
|
|
||||||
use parachain::{ValidationParams, ValidationResult};
|
use parachain::{ValidationParams, ValidationResult};
|
||||||
|
use sc_executor::{call_in_wasm, error::Result, WasmExecutionMethod};
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
use sp_consensus::SelectChain;
|
||||||
|
use sp_io::TestExternalities;
|
||||||
|
use sp_keyring::AccountKeyring;
|
||||||
|
use sp_runtime::{
|
||||||
|
generic::BlockId,
|
||||||
|
traits::{Block as BlockT, Header as HeaderT},
|
||||||
|
};
|
||||||
|
use test_client::{
|
||||||
|
runtime::{Block, Hash, Header, Transfer, WASM_BINARY},
|
||||||
|
Client, DefaultTestClientBuilderExt, LongestChain, TestClientBuilder, TestClientBuilderExt,
|
||||||
|
};
|
||||||
|
|
||||||
use codec::{Encode, Decode};
|
use codec::{Decode, Encode};
|
||||||
|
|
||||||
fn call_validate_block(
|
fn call_validate_block(
|
||||||
parent_head: Header,
|
parent_head: Header,
|
||||||
@@ -39,9 +43,16 @@ fn call_validate_block(
|
|||||||
block_data: block_data.encode(),
|
block_data: block_data.encode(),
|
||||||
parent_head: parent_head.encode(),
|
parent_head: parent_head.encode(),
|
||||||
ingress: Vec::new(),
|
ingress: Vec::new(),
|
||||||
}.encode();
|
}
|
||||||
|
.encode();
|
||||||
|
|
||||||
call_in_wasm(
|
call_in_wasm::<
|
||||||
|
_,
|
||||||
|
(
|
||||||
|
sp_io::SubstrateHostFunctions,
|
||||||
|
sc_executor::deprecated_host_interface::SubstrateExternals,
|
||||||
|
),
|
||||||
|
>(
|
||||||
"validate_block",
|
"validate_block",
|
||||||
¶ms,
|
¶ms,
|
||||||
WasmExecutionMethod::Interpreted,
|
WasmExecutionMethod::Interpreted,
|
||||||
@@ -60,25 +71,29 @@ fn create_extrinsics() -> Vec<<Block as BlockT>::Extrinsic> {
|
|||||||
to: AccountKeyring::Bob.into(),
|
to: AccountKeyring::Bob.into(),
|
||||||
amount: 69,
|
amount: 69,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
}.into_signed_tx(),
|
}
|
||||||
|
.into_signed_tx(),
|
||||||
Transfer {
|
Transfer {
|
||||||
from: AccountKeyring::Alice.into(),
|
from: AccountKeyring::Alice.into(),
|
||||||
to: AccountKeyring::Charlie.into(),
|
to: AccountKeyring::Charlie.into(),
|
||||||
amount: 100,
|
amount: 100,
|
||||||
nonce: 1,
|
nonce: 1,
|
||||||
}.into_signed_tx(),
|
}
|
||||||
|
.into_signed_tx(),
|
||||||
Transfer {
|
Transfer {
|
||||||
from: AccountKeyring::Bob.into(),
|
from: AccountKeyring::Bob.into(),
|
||||||
to: AccountKeyring::Charlie.into(),
|
to: AccountKeyring::Charlie.into(),
|
||||||
amount: 100,
|
amount: 100,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
}.into_signed_tx(),
|
}
|
||||||
|
.into_signed_tx(),
|
||||||
Transfer {
|
Transfer {
|
||||||
from: AccountKeyring::Charlie.into(),
|
from: AccountKeyring::Charlie.into(),
|
||||||
to: AccountKeyring::Alice.into(),
|
to: AccountKeyring::Alice.into(),
|
||||||
amount: 500,
|
amount: 500,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
}.into_signed_tx(),
|
}
|
||||||
|
.into_signed_tx(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,20 +105,25 @@ fn build_block_with_proof(
|
|||||||
client: &Client,
|
client: &Client,
|
||||||
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
|
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
|
||||||
) -> (Block, WitnessData) {
|
) -> (Block, WitnessData) {
|
||||||
let block_id = BlockId::Hash(client.info().chain.best_hash);
|
let block_id = BlockId::Hash(client.info().best_hash);
|
||||||
let mut builder = client.new_block_at(
|
let mut builder = client
|
||||||
&block_id,
|
.new_block_at(&block_id, Default::default(), true)
|
||||||
Default::default(),
|
.expect("Initializes new block");
|
||||||
true,
|
|
||||||
).expect("Initializes new block");
|
|
||||||
|
|
||||||
extrinsics.into_iter().for_each(|e| builder.push(e).expect("Pushes an extrinsic"));
|
extrinsics
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|e| builder.push(e).expect("Pushes an extrinsic"));
|
||||||
|
|
||||||
let (block, proof) = builder
|
let built_block = builder.build().expect("Creates block");
|
||||||
.bake_and_extract_proof()
|
|
||||||
.expect("Finalizes block");
|
|
||||||
|
|
||||||
(block, proof.expect("We enabled proof recording before."))
|
(
|
||||||
|
built_block.block,
|
||||||
|
built_block
|
||||||
|
.proof
|
||||||
|
.expect("We enabled proof recording before.")
|
||||||
|
.iter_nodes()
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -118,7 +138,7 @@ fn validate_block_with_no_extrinsics() {
|
|||||||
header.clone(),
|
header.clone(),
|
||||||
extrinsics,
|
extrinsics,
|
||||||
witness_data,
|
witness_data,
|
||||||
witness_data_storage_root
|
witness_data_storage_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let res_header = call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
let res_header = call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
||||||
@@ -137,7 +157,7 @@ fn validate_block_with_extrinsics() {
|
|||||||
header.clone(),
|
header.clone(),
|
||||||
extrinsics,
|
extrinsics,
|
||||||
witness_data,
|
witness_data,
|
||||||
witness_data_storage_root
|
witness_data_storage_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let res_header = call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
let res_header = call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
||||||
@@ -154,11 +174,7 @@ fn validate_block_invalid_parent_hash() {
|
|||||||
let (mut header, extrinsics) = block.deconstruct();
|
let (mut header, extrinsics) = block.deconstruct();
|
||||||
header.set_parent_hash(Hash::from_low_u64_be(1));
|
header.set_parent_hash(Hash::from_low_u64_be(1));
|
||||||
|
|
||||||
let block_data = ParachainBlockData::new(
|
let block_data =
|
||||||
header,
|
ParachainBlockData::new(header, extrinsics, witness_data, witness_data_storage_root);
|
||||||
extrinsics,
|
|
||||||
witness_data,
|
|
||||||
witness_data_storage_root
|
|
||||||
);
|
|
||||||
call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
test-client = { package = "substrate-test-client", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
test-client = { package = "substrate-test-client", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
runtime = { package = "cumulus-test-runtime", path = "../runtime" }
|
runtime = { package = "cumulus-test-runtime", path = "../runtime" }
|
||||||
runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = [ "derive" ] }
|
codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = [ "derive" ] }
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,18 @@
|
|||||||
|
|
||||||
//! A Cumulus test client.
|
//! A Cumulus test client.
|
||||||
|
|
||||||
pub use test_client::*;
|
|
||||||
pub use runtime;
|
pub use runtime;
|
||||||
use runtime::{Block, genesismap::{GenesisConfig, additional_storage_with_genesis}};
|
use runtime::{
|
||||||
use runtime_primitives::traits::{Hash as HashT, Header as HeaderT, Block as BlockT};
|
genesismap::{additional_storage_with_genesis, GenesisConfig},
|
||||||
use primitives::{storage::well_known_keys, sr25519};
|
Block,
|
||||||
use keyring::{Sr25519Keyring, AccountKeyring};
|
};
|
||||||
|
use sp_core::{sr25519, storage::Storage};
|
||||||
|
use sp_keyring::{AccountKeyring, Sr25519Keyring};
|
||||||
|
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
|
||||||
|
pub use test_client::*;
|
||||||
|
|
||||||
mod local_executor {
|
mod local_executor {
|
||||||
use test_client::executor::native_executor_instance;
|
use test_client::sc_executor::native_executor_instance;
|
||||||
native_executor_instance!(
|
native_executor_instance!(
|
||||||
pub LocalExecutor,
|
pub LocalExecutor,
|
||||||
runtime::api::dispatch,
|
runtime::api::dispatch,
|
||||||
@@ -39,16 +42,17 @@ pub use local_executor::LocalExecutor;
|
|||||||
pub type Backend = test_client::Backend<Block>;
|
pub type Backend = test_client::Backend<Block>;
|
||||||
|
|
||||||
/// Test client executor.
|
/// Test client executor.
|
||||||
pub type Executor = client::LocalCallExecutor<Backend, executor::NativeExecutor<LocalExecutor>>;
|
pub type Executor =
|
||||||
|
sc_client::LocalCallExecutor<Backend, sc_executor::NativeExecutor<LocalExecutor>>;
|
||||||
|
|
||||||
/// Test client builder for Cumulus
|
/// Test client builder for Cumulus
|
||||||
pub type TestClientBuilder = test_client::TestClientBuilder<Executor, Backend, GenesisParameters>;
|
pub type TestClientBuilder = test_client::TestClientBuilder<Executor, Backend, GenesisParameters>;
|
||||||
|
|
||||||
/// LongestChain type for the test runtime/client.
|
/// LongestChain type for the test runtime/client.
|
||||||
pub type LongestChain = test_client::client::LongestChain<Backend, Block>;
|
pub type LongestChain = test_client::sc_client::LongestChain<Backend, Block>;
|
||||||
|
|
||||||
/// Test client type with `LocalExecutor` and generic Backend.
|
/// Test client type with `LocalExecutor` and generic Backend.
|
||||||
pub type Client = client::Client<Backend, Executor, Block, runtime::RuntimeApi>;
|
pub type Client = sc_client::Client<Backend, Executor, Block, runtime::RuntimeApi>;
|
||||||
|
|
||||||
/// Parameters of test-client builder with test-runtime.
|
/// Parameters of test-client builder with test-runtime.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -57,22 +61,24 @@ pub struct GenesisParameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl test_client::GenesisInit for GenesisParameters {
|
impl test_client::GenesisInit for GenesisParameters {
|
||||||
fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) {
|
fn genesis_storage(&self) -> Storage {
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
let mut storage = genesis_config(self.support_changes_trie).genesis_map();
|
|
||||||
storage.0.insert(well_known_keys::CODE.to_vec(), runtime::WASM_BINARY.to_vec());
|
|
||||||
|
|
||||||
let child_roots = storage.1.iter().map(|(sk, child_map)| {
|
let mut storage = genesis_config(self.support_changes_trie).genesis_map();
|
||||||
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
|
||||||
child_map.clone().into_iter().collect()
|
let child_roots = storage.children.iter().map(|(sk, child_content)| {
|
||||||
);
|
let state_root =
|
||||||
|
<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||||
|
child_content.data.clone().into_iter().collect(),
|
||||||
|
);
|
||||||
(sk.clone(), state_root.encode())
|
(sk.clone(), state_root.encode())
|
||||||
});
|
});
|
||||||
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
let state_root =
|
||||||
storage.0.clone().into_iter().chain(child_roots).collect()
|
<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||||
);
|
storage.top.clone().into_iter().chain(child_roots).collect(),
|
||||||
let block: runtime::Block = client::genesis::construct_genesis_block(state_root);
|
);
|
||||||
storage.0.extend(additional_storage_with_genesis(&block));
|
let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root);
|
||||||
|
storage.top.extend(additional_storage_with_genesis(&block));
|
||||||
|
|
||||||
storage
|
storage
|
||||||
}
|
}
|
||||||
@@ -129,7 +135,6 @@ fn genesis_config(support_changes_trie: bool) -> GenesisConfig {
|
|||||||
AccountKeyring::Charlie.into(),
|
AccountKeyring::Charlie.into(),
|
||||||
],
|
],
|
||||||
1000,
|
1000,
|
||||||
None,
|
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,31 +12,33 @@ path = 'src/main.rs'
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
derive_more = '0.15.0'
|
derive_more = '0.15.0'
|
||||||
exit-future = '0.1.4'
|
exit-future = '0.1.4'
|
||||||
futures = '0.1.29'
|
futures = { version = "0.3.1", features = ["compat"] }
|
||||||
futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] }
|
|
||||||
log = '0.4.8'
|
log = '0.4.8'
|
||||||
parking_lot = '0.9.0'
|
parking_lot = '0.9.0'
|
||||||
tokio = '0.1.22'
|
tokio = '0.1.22'
|
||||||
trie-root = '0.15.2'
|
trie-root = '0.15.2'
|
||||||
codec = { package = 'parity-scale-codec', version = '1.0.0' }
|
codec = { package = 'parity-scale-codec', version = '1.0.0' }
|
||||||
parachain-runtime = { package = "cumulus-test-parachain-runtime", path = "runtime" }
|
|
||||||
structopt = "0.3.3"
|
structopt = "0.3.3"
|
||||||
ctrlc = { version = "3.1.3", features = ["termination"] }
|
ctrlc = { version = "3.1.3", features = ["termination"] }
|
||||||
|
|
||||||
|
# Parachain dependencies
|
||||||
|
parachain-runtime = { package = "cumulus-test-parachain-runtime", path = "runtime" }
|
||||||
|
|
||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
sr-primitives = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
sr-io = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-io = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-cli = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-executor = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-service = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
transaction-pool = { package = "substrate-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-service = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
network = { package = "substrate-network", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
substrate-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
srml-timestamp = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-network = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
basic-authorship = { package = "substrate-basic-authorship", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
consensus-common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
sc-basic-authority = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# Cumulus dependencies
|
# Cumulus dependencies
|
||||||
cumulus-consensus = { path = "../../consensus" }
|
cumulus-consensus = { path = "../../consensus" }
|
||||||
@@ -45,6 +47,7 @@ cumulus-collator = { path = "../../collator" }
|
|||||||
# Polkadot dependencies
|
# Polkadot dependencies
|
||||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = '3.0.4'
|
vergen = '3.0.4'
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use std::{env, path::PathBuf};
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
use vergen::{ConstantsFlags, generate_cargo_keys};
|
use vergen::{generate_cargo_keys, ConstantsFlags};
|
||||||
|
|
||||||
const ERROR_MSG: &str = "Failed to generate metadata files";
|
const ERROR_MSG: &str = "Failed to generate metadata files";
|
||||||
|
|
||||||
@@ -24,13 +24,16 @@ fn main() {
|
|||||||
generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG);
|
generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG);
|
||||||
|
|
||||||
let mut manifest_dir = PathBuf::from(
|
let mut manifest_dir = PathBuf::from(
|
||||||
env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo.")
|
env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."),
|
||||||
);
|
);
|
||||||
|
|
||||||
while manifest_dir.parent().is_some() {
|
while manifest_dir.parent().is_some() {
|
||||||
if manifest_dir.join(".git/HEAD").exists() {
|
if manifest_dir.join(".git/HEAD").exists() {
|
||||||
println!("cargo:rerun-if-changed={}", manifest_dir.join(".git/HEAD").display());
|
println!(
|
||||||
return
|
"cargo:rerun-if-changed={}",
|
||||||
|
manifest_dir.join(".git/HEAD").display()
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest_dir.pop();
|
manifest_dir.pop();
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,27 +6,30 @@ edition = '2018'
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||||
safe-mix = { version = "1.0.0", default-features = false }
|
|
||||||
codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-std = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
runtime-io = { package = "sr-io", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-api = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
version = { package = "sr-version", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-io = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
support = { package = "srml-support", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-version = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
substrate-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
sp-core = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
balances = { package = "srml-balances", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
executive = { package = "srml-executive", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
indices = { package = "srml-indices", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
randomness-collective-flip = { package = "srml-randomness-collective-flip", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
system = { package = "srml-system", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
timestamp = { package = "srml-timestamp", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
|
||||||
sudo = { package = "srml-sudo", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
frame-support = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
sr-primitives = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
frame-executive = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
frame-system = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
offchain-primitives = { package = "substrate-offchain-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
pallet-balances = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
transaction-payment = { package = "srml-transaction-payment", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
pallet-indices = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
pallet-sudo = { git = "https://github.com/paritytech/substrate", default_features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
|
||||||
|
|
||||||
# Cumulus dependencies
|
# Cumulus dependencies
|
||||||
cumulus-runtime = { path = "../../../runtime", default-features = false }
|
cumulus-runtime = { path = "../../../runtime", default-features = false }
|
||||||
@@ -38,24 +41,26 @@ wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.
|
|||||||
default = ['std']
|
default = ['std']
|
||||||
std = [
|
std = [
|
||||||
'codec/std',
|
'codec/std',
|
||||||
'client/std',
|
|
||||||
'rstd/std',
|
|
||||||
'runtime-io/std',
|
|
||||||
'support/std',
|
|
||||||
'balances/std',
|
|
||||||
'executive/std',
|
|
||||||
'indices/std',
|
|
||||||
'primitives/std',
|
|
||||||
'sr-primitives/std',
|
|
||||||
'randomness-collective-flip/std',
|
|
||||||
'system/std',
|
|
||||||
'timestamp/std',
|
|
||||||
'sudo/std',
|
|
||||||
'version/std',
|
|
||||||
'serde',
|
'serde',
|
||||||
'safe-mix/std',
|
'sp-api/std',
|
||||||
'offchain-primitives/std',
|
'sp-std/std',
|
||||||
'substrate-session/std',
|
'sp-io/std',
|
||||||
|
'sp-core/std',
|
||||||
|
'sp-runtime/std',
|
||||||
|
'sp-version/std',
|
||||||
|
'sp-offchain/std',
|
||||||
|
'sp-session/std',
|
||||||
|
'sp-block-builder/std',
|
||||||
|
'sp-transaction-pool/std',
|
||||||
|
'sp-inherents/std',
|
||||||
|
'frame-support/std',
|
||||||
|
'frame-executive/std',
|
||||||
|
'frame-system/std',
|
||||||
|
'pallet-balances/std',
|
||||||
|
'pallet-indices/std',
|
||||||
|
'pallet-randomness-collective-flip/std',
|
||||||
|
'pallet-timestamp/std',
|
||||||
|
'pallet-sudo/std',
|
||||||
|
'pallet-transaction-payment/std',
|
||||||
'cumulus-runtime/std',
|
'cumulus-runtime/std',
|
||||||
'transaction-payment/std',
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -16,35 +16,35 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
|
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
|
||||||
#![recursion_limit="256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
// Make the WASM binary available.
|
// Make the WASM binary available.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||||
|
|
||||||
use rstd::prelude::*;
|
use sp_api::impl_runtime_apis;
|
||||||
use primitives::OpaqueMetadata;
|
use sp_core::OpaqueMetadata;
|
||||||
use sr_primitives::{
|
use sp_runtime::traits::{
|
||||||
ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str,
|
BlakeTwo256, Block as BlockT, ConvertInto, NumberFor, StaticLookup, Verify,
|
||||||
impl_opaque_keys, AnySignature
|
|
||||||
};
|
};
|
||||||
use sr_primitives::traits::{NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto};
|
use sp_runtime::{
|
||||||
use sr_primitives::weights::Weight;
|
create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity,
|
||||||
use client::{
|
AnySignature, ApplyExtrinsicResult,
|
||||||
block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api},
|
|
||||||
runtime_api as client_api, impl_runtime_apis
|
|
||||||
};
|
};
|
||||||
use version::RuntimeVersion;
|
use sp_std::prelude::*;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use version::NativeVersion;
|
use sp_version::NativeVersion;
|
||||||
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
// A few exports that help ease life for downstream crates.
|
// A few exports that help ease life for downstream crates.
|
||||||
|
pub use frame_support::{
|
||||||
|
construct_runtime, parameter_types, traits::Randomness, weights::Weight, StorageValue,
|
||||||
|
};
|
||||||
|
pub use pallet_balances::Call as BalancesCall;
|
||||||
|
pub use pallet_timestamp::Call as TimestampCall;
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
pub use sr_primitives::BuildStorage;
|
pub use sp_runtime::BuildStorage;
|
||||||
pub use timestamp::Call as TimestampCall;
|
pub use sp_runtime::{Perbill, Permill};
|
||||||
pub use balances::Call as BalancesCall;
|
|
||||||
pub use sr_primitives::{Permill, Perbill};
|
|
||||||
pub use support::{StorageValue, construct_runtime, parameter_types, traits::Randomness};
|
|
||||||
|
|
||||||
/// An index to a block.
|
/// An index to a block.
|
||||||
pub type BlockNumber = u32;
|
pub type BlockNumber = u32;
|
||||||
@@ -67,7 +67,7 @@ pub type Balance = u128;
|
|||||||
pub type Index = u32;
|
pub type Index = u32;
|
||||||
|
|
||||||
/// A hash of some data used by the chain.
|
/// A hash of some data used by the chain.
|
||||||
pub type Hash = primitives::H256;
|
pub type Hash = sp_core::H256;
|
||||||
|
|
||||||
/// Digest item type.
|
/// Digest item type.
|
||||||
pub type DigestItem = generic::DigestItem<Hash>;
|
pub type DigestItem = generic::DigestItem<Hash>;
|
||||||
@@ -79,7 +79,7 @@ pub type DigestItem = generic::DigestItem<Hash>;
|
|||||||
pub mod opaque {
|
pub mod opaque {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub use sr_primitives::OpaqueExtrinsic as UncheckedExtrinsic;
|
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||||
|
|
||||||
/// Opaque block header type.
|
/// Opaque block header type.
|
||||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||||
@@ -136,7 +136,7 @@ parameter_types! {
|
|||||||
pub const Version: RuntimeVersion = VERSION;
|
pub const Version: RuntimeVersion = VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl system::Trait for Runtime {
|
impl frame_system::Trait for Runtime {
|
||||||
/// The identifier used to distinguish between accounts.
|
/// The identifier used to distinguish between accounts.
|
||||||
type AccountId = AccountId;
|
type AccountId = AccountId;
|
||||||
/// The aggregated dispatch type that is available for extrinsics.
|
/// The aggregated dispatch type that is available for extrinsics.
|
||||||
@@ -165,15 +165,18 @@ impl system::Trait for Runtime {
|
|||||||
type MaximumBlockLength = MaximumBlockLength;
|
type MaximumBlockLength = MaximumBlockLength;
|
||||||
/// Portion of the block weight that is available to all normal transactions.
|
/// Portion of the block weight that is available to all normal transactions.
|
||||||
type AvailableBlockRatio = AvailableBlockRatio;
|
type AvailableBlockRatio = AvailableBlockRatio;
|
||||||
|
/// Runtime version.
|
||||||
type Version = Version;
|
type Version = Version;
|
||||||
|
/// Converts a module to an index of this module in the runtime.
|
||||||
|
type ModuleToIndex = ModuleToIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl indices::Trait for Runtime {
|
impl pallet_indices::Trait for Runtime {
|
||||||
/// The type for recording indexing into the account enumeration. If this ever overflows, there
|
/// The type for recording indexing into the account enumeration. If this ever overflows, there
|
||||||
/// will be problems!
|
/// will be problems!
|
||||||
type AccountIndex = u32;
|
type AccountIndex = u32;
|
||||||
/// Use the standard means of resolving an index hint from an id.
|
/// Use the standard means of resolving an index hint from an id.
|
||||||
type ResolveHint = indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
|
type ResolveHint = pallet_indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
|
||||||
/// Determine whether an account is dead.
|
/// Determine whether an account is dead.
|
||||||
type IsDeadAccount = Balances;
|
type IsDeadAccount = Balances;
|
||||||
/// The ubiquitous event type.
|
/// The ubiquitous event type.
|
||||||
@@ -184,7 +187,7 @@ parameter_types! {
|
|||||||
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
|
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl timestamp::Trait for Runtime {
|
impl pallet_timestamp::Trait for Runtime {
|
||||||
/// A timestamp: milliseconds since the unix epoch.
|
/// A timestamp: milliseconds since the unix epoch.
|
||||||
type Moment = u64;
|
type Moment = u64;
|
||||||
type OnTimestampSet = ();
|
type OnTimestampSet = ();
|
||||||
@@ -199,7 +202,7 @@ parameter_types! {
|
|||||||
pub const TransactionByteFee: u128 = 1;
|
pub const TransactionByteFee: u128 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl balances::Trait for Runtime {
|
impl pallet_balances::Trait for Runtime {
|
||||||
/// The type for recording an account's balance.
|
/// The type for recording an account's balance.
|
||||||
type Balance = Balance;
|
type Balance = Balance;
|
||||||
/// What to do if an account's free balance gets zeroed.
|
/// What to do if an account's free balance gets zeroed.
|
||||||
@@ -215,7 +218,7 @@ impl balances::Trait for Runtime {
|
|||||||
type CreationFee = CreationFee;
|
type CreationFee = CreationFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl transaction_payment::Trait for Runtime {
|
impl pallet_transaction_payment::Trait for Runtime {
|
||||||
type Currency = Balances;
|
type Currency = Balances;
|
||||||
type OnTransactionPayment = ();
|
type OnTransactionPayment = ();
|
||||||
type TransactionBaseFee = TransactionBaseFee;
|
type TransactionBaseFee = TransactionBaseFee;
|
||||||
@@ -224,7 +227,7 @@ impl transaction_payment::Trait for Runtime {
|
|||||||
type FeeMultiplierUpdate = ();
|
type FeeMultiplierUpdate = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sudo::Trait for Runtime {
|
impl pallet_sudo::Trait for Runtime {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
type Proposal = Call;
|
type Proposal = Call;
|
||||||
}
|
}
|
||||||
@@ -235,12 +238,12 @@ construct_runtime! {
|
|||||||
NodeBlock = opaque::Block,
|
NodeBlock = opaque::Block,
|
||||||
UncheckedExtrinsic = UncheckedExtrinsic
|
UncheckedExtrinsic = UncheckedExtrinsic
|
||||||
{
|
{
|
||||||
System: system::{Module, Call, Storage, Config, Event},
|
System: frame_system::{Module, Call, Storage, Config, Event},
|
||||||
Timestamp: timestamp::{Module, Call, Storage, Inherent},
|
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
|
||||||
Indices: indices::{default, Config<T>},
|
Indices: pallet_indices,
|
||||||
Balances: balances::{default, Error},
|
Balances: pallet_balances,
|
||||||
Sudo: sudo,
|
Sudo: pallet_sudo,
|
||||||
RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
|
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,22 +259,28 @@ pub type SignedBlock = generic::SignedBlock<Block>;
|
|||||||
pub type BlockId = generic::BlockId<Block>;
|
pub type BlockId = generic::BlockId<Block>;
|
||||||
/// The SignedExtension to the basic transaction logic.
|
/// The SignedExtension to the basic transaction logic.
|
||||||
pub type SignedExtra = (
|
pub type SignedExtra = (
|
||||||
system::CheckVersion<Runtime>,
|
frame_system::CheckVersion<Runtime>,
|
||||||
system::CheckGenesis<Runtime>,
|
frame_system::CheckGenesis<Runtime>,
|
||||||
system::CheckEra<Runtime>,
|
frame_system::CheckEra<Runtime>,
|
||||||
system::CheckNonce<Runtime>,
|
frame_system::CheckNonce<Runtime>,
|
||||||
system::CheckWeight<Runtime>,
|
frame_system::CheckWeight<Runtime>,
|
||||||
transaction_payment::ChargeTransactionPayment<Runtime>,
|
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||||||
);
|
);
|
||||||
/// Unchecked extrinsic type as expected by this runtime.
|
/// Unchecked extrinsic type as expected by this runtime.
|
||||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
|
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
|
||||||
/// Extrinsic type that has already been checked.
|
/// Extrinsic type that has already been checked.
|
||||||
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
|
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
|
||||||
/// Executive: handles dispatch to the various modules.
|
/// Executive: handles dispatch to the various modules.
|
||||||
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
|
pub type Executive = frame_executive::Executive<
|
||||||
|
Runtime,
|
||||||
|
Block,
|
||||||
|
frame_system::ChainContext<Runtime>,
|
||||||
|
Runtime,
|
||||||
|
AllModules,
|
||||||
|
>;
|
||||||
|
|
||||||
impl_runtime_apis! {
|
impl_runtime_apis! {
|
||||||
impl client_api::Core<Block> for Runtime {
|
impl sp_api::Core<Block> for Runtime {
|
||||||
fn version() -> RuntimeVersion {
|
fn version() -> RuntimeVersion {
|
||||||
VERSION
|
VERSION
|
||||||
}
|
}
|
||||||
@@ -285,14 +294,16 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client_api::Metadata<Block> for Runtime {
|
impl sp_api::Metadata<Block> for Runtime {
|
||||||
fn metadata() -> OpaqueMetadata {
|
fn metadata() -> OpaqueMetadata {
|
||||||
Runtime::metadata().into()
|
Runtime::metadata().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl block_builder_api::BlockBuilder<Block> for Runtime {
|
impl sp_block_builder::BlockBuilder<Block> for Runtime {
|
||||||
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
|
fn apply_extrinsic(
|
||||||
|
extrinsic: <Block as BlockT>::Extrinsic,
|
||||||
|
) -> ApplyExtrinsicResult {
|
||||||
Executive::apply_extrinsic(extrinsic)
|
Executive::apply_extrinsic(extrinsic)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,11 +311,11 @@ impl_runtime_apis! {
|
|||||||
Executive::finalize_block()
|
Executive::finalize_block()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
|
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
|
||||||
data.create_extrinsics()
|
data.create_extrinsics()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
|
fn check_inherents(block: Block, data: sp_inherents::InherentData) -> sp_inherents::CheckInherentsResult {
|
||||||
data.check_extrinsics(&block)
|
data.check_extrinsics(&block)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,21 +324,20 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client_api::TaggedTransactionQueue<Block> for Runtime {
|
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
||||||
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
|
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
|
||||||
Executive::validate_transaction(tx)
|
Executive::validate_transaction(tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
|
||||||
fn offchain_worker(number: NumberFor<Block>) {
|
fn offchain_worker(number: NumberFor<Block>) {
|
||||||
Executive::offchain_worker(number)
|
Executive::offchain_worker(number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl substrate_session::SessionKeys<Block> for Runtime {
|
impl sp_session::SessionKeys<Block> for Runtime {
|
||||||
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
||||||
let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string"));
|
|
||||||
opaque::SessionKeys::generate(seed)
|
opaque::SessionKeys::generate(seed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use substrate_primitives::{Pair, Public};
|
|
||||||
use parachain_runtime::{
|
use parachain_runtime::{
|
||||||
AccountId, BalancesConfig, GenesisConfig, SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY,
|
AccountId, BalancesConfig, GenesisConfig, IndicesConfig, SudoConfig, SystemConfig, WASM_BINARY,
|
||||||
};
|
};
|
||||||
use substrate_service;
|
use sc_service;
|
||||||
|
use sp_core::{Pair, Public};
|
||||||
|
|
||||||
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
|
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
|
||||||
pub type ChainSpec = substrate_service::ChainSpec<GenesisConfig>;
|
pub type ChainSpec = sc_service::ChainSpec<GenesisConfig>;
|
||||||
|
|
||||||
/// Helper function to generate a crypto pair from seed
|
/// Helper function to generate a crypto pair from seed
|
||||||
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
||||||
@@ -32,7 +32,10 @@ pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Pu
|
|||||||
|
|
||||||
/// Helper function to generate stash, controller and session key from seed
|
/// Helper function to generate stash, controller and session key from seed
|
||||||
pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId) {
|
pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId) {
|
||||||
(get_from_seed::<AccountId>(&format!("{}//stash", seed)), get_from_seed::<AccountId>(seed))
|
(
|
||||||
|
get_from_seed::<AccountId>(&format!("{}//stash", seed)),
|
||||||
|
get_from_seed::<AccountId>(seed),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the chain spec.
|
/// Returns the chain spec.
|
||||||
@@ -40,28 +43,30 @@ pub fn get_chain_spec() -> ChainSpec {
|
|||||||
ChainSpec::from_genesis(
|
ChainSpec::from_genesis(
|
||||||
"Local Testnet",
|
"Local Testnet",
|
||||||
"parachain_local_testnet",
|
"parachain_local_testnet",
|
||||||
|| testnet_genesis(
|
|| {
|
||||||
vec![
|
testnet_genesis(
|
||||||
get_authority_keys_from_seed("Alice"),
|
vec![
|
||||||
get_authority_keys_from_seed("Bob"),
|
get_authority_keys_from_seed("Alice"),
|
||||||
],
|
get_authority_keys_from_seed("Bob"),
|
||||||
get_from_seed::<AccountId>("Alice"),
|
],
|
||||||
vec![
|
|
||||||
get_from_seed::<AccountId>("Alice"),
|
get_from_seed::<AccountId>("Alice"),
|
||||||
get_from_seed::<AccountId>("Bob"),
|
vec![
|
||||||
get_from_seed::<AccountId>("Charlie"),
|
get_from_seed::<AccountId>("Alice"),
|
||||||
get_from_seed::<AccountId>("Dave"),
|
get_from_seed::<AccountId>("Bob"),
|
||||||
get_from_seed::<AccountId>("Eve"),
|
get_from_seed::<AccountId>("Charlie"),
|
||||||
get_from_seed::<AccountId>("Ferdie"),
|
get_from_seed::<AccountId>("Dave"),
|
||||||
get_from_seed::<AccountId>("Alice//stash"),
|
get_from_seed::<AccountId>("Eve"),
|
||||||
get_from_seed::<AccountId>("Bob//stash"),
|
get_from_seed::<AccountId>("Ferdie"),
|
||||||
get_from_seed::<AccountId>("Charlie//stash"),
|
get_from_seed::<AccountId>("Alice//stash"),
|
||||||
get_from_seed::<AccountId>("Dave//stash"),
|
get_from_seed::<AccountId>("Bob//stash"),
|
||||||
get_from_seed::<AccountId>("Eve//stash"),
|
get_from_seed::<AccountId>("Charlie//stash"),
|
||||||
get_from_seed::<AccountId>("Ferdie//stash"),
|
get_from_seed::<AccountId>("Dave//stash"),
|
||||||
],
|
get_from_seed::<AccountId>("Eve//stash"),
|
||||||
true,
|
get_from_seed::<AccountId>("Ferdie//stash"),
|
||||||
),
|
],
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
},
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
@@ -77,19 +82,21 @@ fn testnet_genesis(
|
|||||||
_enable_println: bool,
|
_enable_println: bool,
|
||||||
) -> GenesisConfig {
|
) -> GenesisConfig {
|
||||||
GenesisConfig {
|
GenesisConfig {
|
||||||
system: Some(SystemConfig {
|
frame_system: Some(SystemConfig {
|
||||||
code: WASM_BINARY.to_vec(),
|
code: WASM_BINARY.to_vec(),
|
||||||
changes_trie_config: Default::default(),
|
changes_trie_config: Default::default(),
|
||||||
}),
|
}),
|
||||||
indices: Some(IndicesConfig {
|
pallet_indices: Some(IndicesConfig {
|
||||||
ids: endowed_accounts.clone(),
|
ids: endowed_accounts.clone(),
|
||||||
}),
|
}),
|
||||||
balances: Some(BalancesConfig {
|
pallet_balances: Some(BalancesConfig {
|
||||||
balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),
|
balances: endowed_accounts
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|k| (k, 1 << 60))
|
||||||
|
.collect(),
|
||||||
vesting: vec![],
|
vesting: vec![],
|
||||||
}),
|
}),
|
||||||
sudo: Some(SudoConfig {
|
pallet_sudo: Some(SudoConfig { key: root_key }),
|
||||||
key: root_key,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,23 +18,29 @@ use crate::chain_spec;
|
|||||||
|
|
||||||
use parachain_runtime::Block;
|
use parachain_runtime::Block;
|
||||||
|
|
||||||
pub use substrate_cli::{VersionInfo, IntoExit, error::{self, Result}};
|
pub use sc_cli::{
|
||||||
use substrate_cli::{parse_and_prepare, ParseAndPrepare, NoCustom};
|
error::{self, Result},
|
||||||
use substrate_service::{Roles as ServiceRoles, Configuration};
|
IntoExit, VersionInfo,
|
||||||
use sr_primitives::{traits::{Block as BlockT, Header as HeaderT, Hash as HashT}, BuildStorage};
|
};
|
||||||
use substrate_client::genesis;
|
use sc_cli::{parse_and_prepare, NoCustom, ParseAndPrepare};
|
||||||
use substrate_primitives::hexdisplay::HexDisplay;
|
use sc_client::genesis;
|
||||||
|
use sc_service::{Configuration, Roles as ServiceRoles};
|
||||||
|
use sp_core::hexdisplay::HexDisplay;
|
||||||
|
use sp_runtime::{
|
||||||
|
traits::{Block as BlockT, Hash as HashT, Header as HeaderT},
|
||||||
|
BuildStorage,
|
||||||
|
};
|
||||||
|
|
||||||
|
use futures::{channel::oneshot, future::Map, FutureExt};
|
||||||
|
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use std::{path::PathBuf, cell::RefCell, sync::Arc};
|
use std::{cell::RefCell, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use futures::{sync::oneshot, future, Future};
|
|
||||||
|
|
||||||
/// Sub-commands supported by the collator.
|
/// Sub-commands supported by the collator.
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
enum SubCommands {
|
enum SubCommands {
|
||||||
@@ -43,8 +49,10 @@ enum SubCommands {
|
|||||||
ExportGenesisState(ExportGenesisStateCommand),
|
ExportGenesisState(ExportGenesisStateCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl substrate_cli::GetLogFilter for SubCommands {
|
impl sc_cli::GetSharedParams for SubCommands {
|
||||||
fn get_log_filter(&self) -> Option<String> { None }
|
fn shared_params(&self) -> Option<&sc_cli::SharedParams> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Command for exporting the genesis state of the parachain
|
/// Command for exporting the genesis state of the parachain
|
||||||
@@ -57,10 +65,10 @@ struct ExportGenesisStateCommand {
|
|||||||
|
|
||||||
/// Parse command line arguments into service configuration.
|
/// Parse command line arguments into service configuration.
|
||||||
pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
|
pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = T>,
|
I: IntoIterator<Item = T>,
|
||||||
T: Into<std::ffi::OsString> + Clone,
|
T: Into<std::ffi::OsString> + Clone,
|
||||||
E: IntoExit + Send + 'static,
|
E: IntoExit + Send + 'static,
|
||||||
{
|
{
|
||||||
type Config<T> = Configuration<(), T>;
|
type Config<T> = Configuration<(), T>;
|
||||||
match parse_and_prepare::<SubCommands, NoCustom, _>(
|
match parse_and_prepare::<SubCommands, NoCustom, _>(
|
||||||
@@ -68,37 +76,68 @@ pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
|
|||||||
"cumulus-test-parachain-collator",
|
"cumulus-test-parachain-collator",
|
||||||
args,
|
args,
|
||||||
) {
|
) {
|
||||||
ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit,
|
ParseAndPrepare::Run(cmd) => cmd.run(
|
||||||
|exit, _cli_args, _custom_args, mut config: Config<_>| {
|
load_spec,
|
||||||
info!("{}", version.name);
|
exit,
|
||||||
info!(" version {}", config.full_version());
|
|exit, _cli_args, _custom_args, mut config: Config<_>| {
|
||||||
info!(" by {}, 2019", version.author);
|
info!("{}", version.name);
|
||||||
info!("Chain specification: {}", config.chain_spec.name());
|
info!(" version {}", config.full_version());
|
||||||
info!("Node name: {}", config.name);
|
info!(" by {}, 2019", version.author);
|
||||||
info!("Roles: {:?}", config.roles);
|
info!("Chain specification: {}", config.chain_spec.name());
|
||||||
info!("Parachain id: {:?}", crate::PARA_ID);
|
info!("Node name: {}", config.name);
|
||||||
|
info!("Roles: {:?}", config.roles);
|
||||||
|
info!("Parachain id: {:?}", crate::PARA_ID);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
let key = Arc::new(substrate_primitives::Pair::from_seed(&[10; 32]));
|
let key = Arc::new(sp_core::Pair::from_seed(&[10; 32]));
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
config.network.listen_addresses = Vec::new();
|
config.network.listen_addresses = Vec::new();
|
||||||
config.network.boot_nodes = vec![];
|
|
||||||
config.chain_spec = chain_spec::get_chain_spec();
|
|
||||||
|
|
||||||
match config.roles {
|
// TODO
|
||||||
ServiceRoles::LIGHT => unimplemented!("Light client not supported!"),
|
let mut polkadot_config =
|
||||||
_ => crate::service::run_collator(config, exit, key, version.clone()),
|
polkadot_collator::Configuration::default_with_spec_and_base_path(
|
||||||
}.map_err(|e| format!("{:?}", e))
|
polkadot_service::ChainSpec::from_json_bytes(
|
||||||
}),
|
&include_bytes!("../res/polkadot_chainspec.json")[..],
|
||||||
ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec),
|
)?,
|
||||||
ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>|
|
config.in_chain_config_dir("polkadot"),
|
||||||
Ok(new_full_start!(config).0), load_spec, exit),
|
);
|
||||||
ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>|
|
polkadot_config.network.boot_nodes = config.network.boot_nodes.clone();
|
||||||
Ok(new_full_start!(config).0), load_spec, exit),
|
|
||||||
|
if let Some(ref config_dir) = polkadot_config.config_dir {
|
||||||
|
polkadot_config.database = sc_service::config::DatabaseConfig::Path {
|
||||||
|
cache_size: Default::default(),
|
||||||
|
path: config_dir.join("db"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
match config.roles {
|
||||||
|
ServiceRoles::LIGHT => unimplemented!("Light client not supported!"),
|
||||||
|
_ => crate::service::run_collator(config, exit, key, polkadot_config),
|
||||||
|
}
|
||||||
|
.map_err(|e| format!("{:?}", e))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ParseAndPrepare::BuildSpec(cmd) => cmd.run::<NoCustom, _, _, _>(load_spec),
|
||||||
|
ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(
|
||||||
|
|config: Config<_>| Ok(new_full_start!(config).0),
|
||||||
|
load_spec,
|
||||||
|
exit,
|
||||||
|
),
|
||||||
|
ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(
|
||||||
|
|config: Config<_>| Ok(new_full_start!(config).0),
|
||||||
|
load_spec,
|
||||||
|
exit,
|
||||||
|
),
|
||||||
|
ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(
|
||||||
|
|config: Config<_>| Ok(new_full_start!(config).0),
|
||||||
|
load_spec,
|
||||||
|
exit,
|
||||||
|
),
|
||||||
ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
|
ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
|
||||||
ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>|
|
ParseAndPrepare::RevertChain(cmd) => {
|
||||||
Ok(new_full_start!(config).0), load_spec),
|
cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec)
|
||||||
|
}
|
||||||
ParseAndPrepare::CustomCommand(SubCommands::ExportGenesisState(cmd)) => {
|
ParseAndPrepare::CustomCommand(SubCommands::ExportGenesisState(cmd)) => {
|
||||||
export_genesis_state(cmd.output)
|
export_genesis_state(cmd.output)
|
||||||
}
|
}
|
||||||
@@ -113,16 +152,16 @@ fn load_spec(_: &str) -> std::result::Result<Option<chain_spec::ChainSpec>, Stri
|
|||||||
|
|
||||||
/// Export the genesis state of the parachain.
|
/// Export the genesis state of the parachain.
|
||||||
fn export_genesis_state(output: Option<PathBuf>) -> error::Result<()> {
|
fn export_genesis_state(output: Option<PathBuf>) -> error::Result<()> {
|
||||||
let storage = chain_spec::get_chain_spec().build_storage()?;
|
let storage = (&chain_spec::get_chain_spec()).build_storage()?;
|
||||||
|
|
||||||
let child_roots = storage.1.iter().map(|(sk, child_map)| {
|
let child_roots = storage.children.iter().map(|(sk, child_content)| {
|
||||||
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||||
child_map.clone().into_iter().collect()
|
child_content.data.clone().into_iter().collect(),
|
||||||
);
|
);
|
||||||
(sk.clone(), state_root.encode())
|
(sk.clone(), state_root.encode())
|
||||||
});
|
});
|
||||||
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||||
storage.0.clone().into_iter().chain(child_roots).collect()
|
storage.top.clone().into_iter().chain(child_roots).collect(),
|
||||||
);
|
);
|
||||||
let block: Block = genesis::construct_genesis_block(state_root);
|
let block: Block = genesis::construct_genesis_block(state_root);
|
||||||
|
|
||||||
@@ -140,19 +179,23 @@ fn export_genesis_state(output: Option<PathBuf>) -> error::Result<()> {
|
|||||||
// handles ctrl-c
|
// handles ctrl-c
|
||||||
pub struct Exit;
|
pub struct Exit;
|
||||||
impl IntoExit for Exit {
|
impl IntoExit for Exit {
|
||||||
type Exit = future::MapErr<oneshot::Receiver<()>, fn(oneshot::Canceled) -> ()>;
|
type Exit = Map<oneshot::Receiver<()>, fn(std::result::Result<(), oneshot::Canceled>) -> ()>;
|
||||||
fn into_exit(self) -> Self::Exit {
|
fn into_exit(self) -> Self::Exit {
|
||||||
// can't use signal directly here because CtrlC takes only `Fn`.
|
// can't use signal directly here because CtrlC takes only `Fn`.
|
||||||
let (exit_send, exit) = oneshot::channel();
|
let (exit_send, exit) = oneshot::channel();
|
||||||
|
|
||||||
let exit_send_cell = RefCell::new(Some(exit_send));
|
let exit_send_cell = RefCell::new(Some(exit_send));
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
let exit_send = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take();
|
let exit_send = exit_send_cell
|
||||||
|
.try_borrow_mut()
|
||||||
|
.expect("signal handler not reentrant; qed")
|
||||||
|
.take();
|
||||||
if let Some(exit_send) = exit_send {
|
if let Some(exit_send) = exit_send {
|
||||||
exit_send.send(()).expect("Error sending exit notification");
|
exit_send.send(()).expect("Error sending exit notification");
|
||||||
}
|
}
|
||||||
}).expect("Error setting Ctrl-C handler");
|
})
|
||||||
|
.expect("Error setting Ctrl-C handler");
|
||||||
|
|
||||||
exit.map_err(drop)
|
exit.map(drop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ mod chain_spec;
|
|||||||
mod service;
|
mod service;
|
||||||
mod cli;
|
mod cli;
|
||||||
|
|
||||||
pub use substrate_cli::{VersionInfo, IntoExit, error};
|
pub use sc_cli::{error, IntoExit, VersionInfo};
|
||||||
|
|
||||||
/// The parachain id of this parachain.
|
/// The parachain id of this parachain.
|
||||||
pub const PARA_ID: ParaId = ParaId::new(100);
|
pub const PARA_ID: ParaId = ParaId::new(100);
|
||||||
|
|||||||
@@ -16,20 +16,19 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use parachain_runtime::{self, GenesisConfig, opaque::Block};
|
use parachain_runtime::{self, opaque::Block, GenesisConfig};
|
||||||
|
|
||||||
use inherents::InherentDataProviders;
|
use sc_executor::native_executor_instance;
|
||||||
use substrate_service::{AbstractService, Configuration};
|
use sc_network::construct_simple_protocol;
|
||||||
use network::construct_simple_protocol;
|
use sc_service::{AbstractService, Configuration};
|
||||||
use substrate_executor::native_executor_instance;
|
use sp_consensus::{BlockImport, Environment, Proposer};
|
||||||
|
use sp_inherents::InherentDataProviders;
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::{compat::Future01CompatExt, future, task::Spawn, FutureExt, TryFutureExt};
|
||||||
|
|
||||||
use futures03::FutureExt;
|
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
pub use substrate_executor::NativeExecutor;
|
pub use sc_executor::NativeExecutor;
|
||||||
|
|
||||||
// Our native executor instance.
|
// Our native executor instance.
|
||||||
native_executor_instance!(
|
native_executor_instance!(
|
||||||
@@ -49,29 +48,35 @@ construct_simple_protocol! {
|
|||||||
/// be able to perform chain operations.
|
/// be able to perform chain operations.
|
||||||
macro_rules! new_full_start {
|
macro_rules! new_full_start {
|
||||||
($config:expr) => {{
|
($config:expr) => {{
|
||||||
let inherent_data_providers = inherents::InherentDataProviders::new();
|
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
||||||
|
|
||||||
let builder = substrate_service::ServiceBuilder::new_full::<
|
let builder = sc_service::ServiceBuilder::new_full::<
|
||||||
parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor,
|
parachain_runtime::opaque::Block,
|
||||||
|
parachain_runtime::RuntimeApi,
|
||||||
|
crate::service::Executor,
|
||||||
>($config)?
|
>($config)?
|
||||||
.with_select_chain(|_config, backend| {
|
.with_select_chain(|_config, backend| Ok(sc_client::LongestChain::new(backend.clone())))?
|
||||||
Ok(substrate_client::LongestChain::new(backend.clone()))
|
.with_transaction_pool(|config, client, _| {
|
||||||
})?
|
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
|
||||||
.with_transaction_pool(|config, client|
|
let pool = sc_transaction_pool::BasicPool::new(config, pool_api);
|
||||||
Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client)))
|
let maintainer =
|
||||||
)?
|
sc_transaction_pool::FullBasicPoolMaintainer::new(pool.pool().clone(), client);
|
||||||
.with_import_queue(|_config, client, _, _| {
|
let maintainable_pool =
|
||||||
let import_queue = cumulus_consensus::import_queue::import_queue(
|
sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer);
|
||||||
client.clone(),
|
Ok(maintainable_pool)
|
||||||
client,
|
})?
|
||||||
inherent_data_providers.clone(),
|
.with_import_queue(|_config, client, _, _| {
|
||||||
)?;
|
let import_queue = cumulus_consensus::import_queue::import_queue(
|
||||||
|
client.clone(),
|
||||||
|
client,
|
||||||
|
inherent_data_providers.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(import_queue)
|
Ok(import_queue)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
(builder, inherent_data_providers)
|
(builder, inherent_data_providers)
|
||||||
}}
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the collator with the given `config`.
|
/// Run the collator with the given `config`.
|
||||||
@@ -79,13 +84,17 @@ pub fn run_collator<C: Send + Default + 'static, E: crate::cli::IntoExit + Send
|
|||||||
config: Configuration<C, GenesisConfig>,
|
config: Configuration<C, GenesisConfig>,
|
||||||
exit: E,
|
exit: E,
|
||||||
key: Arc<polkadot_primitives::parachain::CollatorPair>,
|
key: Arc<polkadot_primitives::parachain::CollatorPair>,
|
||||||
version: crate::cli::VersionInfo,
|
polkadot_config: polkadot_collator::Configuration,
|
||||||
) -> crate::cli::Result<()> {
|
) -> crate::cli::Result<()> {
|
||||||
let (builder, inherent_data_providers) = new_full_start!(config);
|
let (builder, inherent_data_providers) = new_full_start!(config);
|
||||||
inherent_data_providers.register_provider(srml_timestamp::InherentDataProvider).unwrap();
|
inherent_data_providers
|
||||||
|
.register_provider(sp_timestamp::InherentDataProvider)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let service = builder.with_network_protocol(|_| Ok(NodeProtocol::new()))?.build()?;
|
let service = builder
|
||||||
let proposer_factory = basic_authorship::ProposerFactory {
|
.with_network_protocol(|_| Ok(NodeProtocol::new()))?
|
||||||
|
.build()?;
|
||||||
|
let proposer_factory = sc_basic_authority::ProposerFactory {
|
||||||
client: service.client(),
|
client: service.client(),
|
||||||
transaction_pool: service.transaction_pool(),
|
transaction_pool: service.transaction_pool(),
|
||||||
};
|
};
|
||||||
@@ -101,7 +110,13 @@ pub fn run_collator<C: Send + Default + 'static, E: crate::cli::IntoExit + Send
|
|||||||
block_import,
|
block_import,
|
||||||
};
|
};
|
||||||
|
|
||||||
cumulus_collator::run_collator(setup_parachain, crate::PARA_ID, on_exit, key, version)
|
cumulus_collator::run_collator(
|
||||||
|
setup_parachain,
|
||||||
|
crate::PARA_ID,
|
||||||
|
on_exit,
|
||||||
|
key,
|
||||||
|
polkadot_config,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SetupParachain<S, PF, E, BI> {
|
struct SetupParachain<S, PF, E, BI> {
|
||||||
@@ -112,43 +127,66 @@ struct SetupParachain<S, PF, E, BI> {
|
|||||||
block_import: BI,
|
block_import: BI,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TransactionFor<E, Block> =
|
||||||
|
<<E as Environment<Block>>::Proposer as Proposer<Block>>::Transaction;
|
||||||
|
|
||||||
impl<S, PF, E, BI> cumulus_collator::SetupParachain<Block> for SetupParachain<S, PF, E, BI>
|
impl<S, PF, E, BI> cumulus_collator::SetupParachain<Block> for SetupParachain<S, PF, E, BI>
|
||||||
where
|
where
|
||||||
S: AbstractService,
|
S: AbstractService,
|
||||||
E: Send + crate::cli::IntoExit,
|
E: Send + crate::cli::IntoExit,
|
||||||
PF: consensus_common::Environment<Block> + Send + 'static,
|
PF: Environment<Block> + Send + 'static,
|
||||||
BI: consensus_common::BlockImport<Block, Error=consensus_common::Error> + Send + Sync + 'static,
|
BI: BlockImport<Block, Error = sp_consensus::Error, Transaction = TransactionFor<PF, Block>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
{
|
{
|
||||||
type ProposerFactory = PF;
|
type ProposerFactory = PF;
|
||||||
type BlockImport = BI;
|
type BlockImport = BI;
|
||||||
|
|
||||||
fn setup_parachain<P: cumulus_consensus::PolkadotClient>(
|
fn setup_parachain<P: cumulus_consensus::PolkadotClient, Spawner>(
|
||||||
self,
|
self,
|
||||||
polkadot_client: P,
|
polkadot_client: P,
|
||||||
task_executor: polkadot_collator::TaskExecutor,
|
spawner: Spawner,
|
||||||
) -> Result<(Self::ProposerFactory, Self::BlockImport, InherentDataProviders), String> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
Self::ProposerFactory,
|
||||||
|
Self::BlockImport,
|
||||||
|
InherentDataProviders,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
Spawner: Spawn + Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
let client = self.service.client();
|
let client = self.service.client();
|
||||||
|
|
||||||
let follow = match cumulus_consensus::follow_polkadot(crate::PARA_ID, client, polkadot_client) {
|
let follow =
|
||||||
Ok(follow) => follow,
|
match cumulus_consensus::follow_polkadot(crate::PARA_ID, client, polkadot_client) {
|
||||||
Err(e) => {
|
Ok(follow) => follow,
|
||||||
return Err(format!("Could not start following polkadot: {:?}", e));
|
Err(e) => {
|
||||||
}
|
return Err(format!("Could not start following polkadot: {:?}", e));
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
task_executor.execute(
|
spawner
|
||||||
Box::new(
|
.spawn_obj(
|
||||||
self.service
|
Box::new(
|
||||||
.map_err(|e| error!("Parachain service error: {:?}", e))
|
future::select(
|
||||||
.select(futures03::compat::Compat::new(follow.map(|_| Ok::<(), ()>(()))))
|
self.service
|
||||||
.map(|_| ())
|
.compat()
|
||||||
.map_err(|_| ())
|
.map_err(|e| error!("Parachain service error: {:?}", e)),
|
||||||
.select(self.exit.into_exit())
|
future::select(follow, self.exit.into_exit()),
|
||||||
.map(|_| ())
|
)
|
||||||
.map_err(|_| ())
|
.map(|_| ()),
|
||||||
),
|
)
|
||||||
).map_err(|_| "Could not spawn parachain server!")?;
|
.into(),
|
||||||
|
)
|
||||||
|
.map_err(|_| "Could not spawn parachain server!")?;
|
||||||
|
|
||||||
Ok((self.proposer_factory, self.block_import, self.inherent_data_providers))
|
Ok((
|
||||||
|
self.proposer_factory,
|
||||||
|
self.block_import,
|
||||||
|
self.inherent_data_providers,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
|||||||
|
|
||||||
pub use substrate_test_runtime::*;
|
pub use substrate_test_runtime::*;
|
||||||
|
|
||||||
runtime::register_validate_block!(Block, system::BlockExecutor);
|
runtime::register_validate_block!(Block, system::BlockExecutor);
|
||||||
|
|||||||
Reference in New Issue
Block a user