,
+ /// Transaction pool instance.
+ pub pool: Arc,
+ /// Remote access to the blockchain (async).
+ pub remote_blockchain: Arc>,
+ /// Fetcher instance.
+ pub fetcher: Arc,
+}
+
+/// Extra dependencies for BABE.
+pub struct BabeDeps {
+ /// BABE protocol config.
+ pub babe_config: Config,
+ /// BABE pending epoch changes.
+ pub shared_epoch_changes: SharedEpochChanges,
+ /// The keystore that manages the keys of the node.
+ pub keystore: KeyStorePtr,
+}
+
+/// Extra dependencies for GRANDPA
+pub struct GrandpaDeps {
+ /// Voting round info.
+ pub shared_voter_state: SharedVoterState,
+ /// Authority set info.
+ pub shared_authority_set: SharedAuthoritySet,
+}
+
+/// Full client dependencies.
+pub struct FullDeps {
+ /// The client instance to use.
+ pub client: Arc,
+ /// Transaction pool instance.
+ pub pool: Arc,
+ /// The SelectChain Strategy
+ pub select_chain: SC,
+ /// Whether to deny unsafe calls
+ pub deny_unsafe: DenyUnsafe,
+ /// BABE specific dependencies.
+ pub babe: BabeDeps,
+ /// GRANDPA specific dependencies.
+ pub grandpa: GrandpaDeps,
+}
+
+/// Instantiate all Full RPC extensions.
+pub fn create_full(deps: FullDeps) -> jsonrpc_core::IoHandler
+where
+ C: ProvideRuntimeApi,
+ C: HeaderBackend + HeaderMetadata + 'static,
+ C: Send + Sync + 'static,
+ C::Api: substrate_frame_rpc_system::AccountNonceApi,
+ C::Api: pallet_contracts_rpc::ContractsRuntimeApi,
+ C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<
+ Block,
+ Balance,
+ UncheckedExtrinsic,
+ >,
+ C::Api: BabeApi,
+ C::Api: BlockBuilder,
+ P: TransactionPool + 'static,
+ M: jsonrpc_core::Metadata + Default,
+ SC: SelectChain + 'static,
+{
+ use pallet_contracts_rpc::{Contracts, ContractsApi};
+ use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
+ use substrate_frame_rpc_system::{FullSystem, SystemApi};
+
+ let mut io = jsonrpc_core::IoHandler::default();
+ let FullDeps {
+ client,
+ pool,
+ select_chain,
+ deny_unsafe,
+ babe,
+ grandpa,
+ } = deps;
+ let BabeDeps {
+ keystore,
+ babe_config,
+ shared_epoch_changes,
+ } = babe;
+ let GrandpaDeps {
+ shared_voter_state,
+ shared_authority_set,
+ } = grandpa;
+
+ io.extend_with(SystemApi::to_delegate(FullSystem::new(
+ client.clone(),
+ pool,
+ deny_unsafe,
+ )));
+ // Making synchronous calls in light client freezes the browser currently,
+ // more context: https://github.com/paritytech/substrate/pull/3480
+ // These RPCs should use an asynchronous caller instead.
+ io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone())));
+ io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(
+ client.clone(),
+ )));
+ io.extend_with(sc_consensus_babe_rpc::BabeApi::to_delegate(
+ BabeRpcHandler::new(
+ client,
+ shared_epoch_changes,
+ keystore,
+ babe_config,
+ select_chain,
+ deny_unsafe,
+ ),
+ ));
+ io.extend_with(sc_finality_grandpa_rpc::GrandpaApi::to_delegate(
+ GrandpaRpcHandler::new(shared_authority_set, shared_voter_state),
+ ));
+
+ io
+}
+
+/// Instantiate all Light RPC extensions.
+pub fn create_light(deps: LightDeps) -> jsonrpc_core::IoHandler
+where
+ C: sp_blockchain::HeaderBackend,
+ C: Send + Sync + 'static,
+ F: sc_client_api::light::Fetcher + 'static,
+ P: TransactionPool + 'static,
+ M: jsonrpc_core::Metadata + Default,
+{
+ use substrate_frame_rpc_system::{LightSystem, SystemApi};
+
+ let LightDeps {
+ client,
+ pool,
+ remote_blockchain,
+ fetcher,
+ } = deps;
+ let mut io = jsonrpc_core::IoHandler::default();
+ io.extend_with(SystemApi::::to_delegate(
+ LightSystem::new(client, remote_blockchain, fetcher, pool),
+ ));
+
+ io
+}
diff --git a/node/src/service.rs b/node/src/service.rs
index 64bf0a03d9..a1ebae62c5 100644
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -16,107 +16,141 @@
#![warn(unused_extern_crates)]
-// Clippy linter warning.
-#![allow(clippy::type_complexity)] // disable it because this is foreign code and can be changed any time
-
-// Clippy linter warning.
-#![allow(clippy::redundant_closure_call)] // disable it because of the substrate lib design
-
-//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
-
-use client_db::Backend;
-use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
-use inherents::InherentDataProviders;
-use network::{construct_simple_protocol, NetworkService};
-use node_runtime::{self, opaque::Block, GenesisConfig, RuntimeApi};
-use offchain::OffchainWorkers;
-use primitives::Blake2Hasher;
-use runtime_primitives::traits::Block as BlockT;
-use std::sync::Arc;
-use substrate_client::{Client, LocalCallExecutor, LongestChain};
-pub use substrate_executor::{native_executor_instance, NativeExecutor};
-use substrate_service::{
- error::Error as ServiceError, AbstractService, Configuration, NetworkStatus, Service,
- ServiceBuilder,
-};
-use transaction_pool::{self, txpool::Pool as TransactionPool};
+// Substrate implementation issue.
+#![allow(clippy::redundant_closure_call)]
-construct_simple_protocol! {
- /// Demo protocol attachment for substrate.
- pub struct NodeProtocol where Block = Block { }
-}
+//! Service implementation. Specialized wrapper over substrate service.
+
+use node_runtime::opaque::Block;
+use node_runtime::RuntimeApi;
+use sc_consensus::LongestChain;
+use sc_finality_grandpa::{
+ self as grandpa, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider,
+};
+use sc_service::{
+ config::Configuration, error::Error as ServiceError, AbstractService, ServiceBuilder,
+};
+use sp_inherents::InherentDataProviders;
+use std::sync::Arc;
-// Declare an instance of the native executor named `Executor`. Include the wasm binary as the
-// equivalent wasm code.
-native_executor_instance!(
- pub Executor,
- node_runtime::api::dispatch,
- node_runtime::native_version
-);
+use crate::node_executor;
+use crate::node_rpc;
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to
/// be able to perform chain operations.
-#[macro_export]
macro_rules! new_full_start {
($config:expr) => {{
- // type RpcExtension = jsonrpc_core::IoHandler;
+ use std::sync::Arc;
+
let mut import_setup = None;
- let inherent_data_providers = inherents::InherentDataProviders::new();
+ let mut rpc_setup = None;
+ let inherent_data_providers = sp_inherents::InherentDataProviders::new();
- let builder = substrate_service::ServiceBuilder::new_full::<
- node_runtime::opaque::Block,
- node_runtime::RuntimeApi,
- crate::service::Executor,
+ let builder = sc_service::ServiceBuilder::new_full::<
+ Block,
+ RuntimeApi,
+ node_executor::Executor,
>($config)?
- .with_select_chain(|_config, backend| {
- Ok(substrate_client::LongestChain::new(backend.clone()))
- })?
- .with_transaction_pool(|config, client| {
- Ok(transaction_pool::txpool::Pool::new(
- config,
- transaction_pool::FullChainApi::new(client),
+ .with_select_chain(|_config, backend| Ok(sc_consensus::LongestChain::new(backend.clone())))?
+ .with_transaction_pool(|builder| {
+ let pool_api = sc_transaction_pool::FullChainApi::new(builder.client().clone());
+ let config = builder.config();
+
+ Ok(sc_transaction_pool::BasicPool::new(
+ config.transaction_pool.clone(),
+ std::sync::Arc::new(pool_api),
+ builder.prometheus_registry(),
))
})?
- .with_import_queue(|_config, client, mut select_chain, _transaction_pool| {
- let select_chain = select_chain
- .take()
- .ok_or_else(|| substrate_service::Error::SelectChainRequired)?;
- let (grandpa_block_import, grandpa_link) =
- grandpa::block_import::<_, _, _, node_runtime::RuntimeApi, _>(
+ .with_import_queue(
+ |_config,
+ client,
+ mut select_chain,
+ _transaction_pool,
+ spawn_task_handle,
+ prometheus_registry| {
+ let select_chain = select_chain
+ .take()
+ .ok_or_else(|| sc_service::Error::SelectChainRequired)?;
+ let (grandpa_block_import, grandpa_link) = grandpa::block_import(
client.clone(),
- &*client,
+ &(client.clone() as Arc<_>),
select_chain,
)?;
- let justification_import = grandpa_block_import.clone();
-
- let (block_import, babe_link) = babe::block_import(
- babe::Config::get_or_compute(&*client)?,
- grandpa_block_import,
- client.clone(),
- client.clone(),
- )?;
-
- let import_queue = babe::import_queue(
- babe_link.clone(),
- block_import.clone(),
- Some(Box::new(justification_import)),
- None,
- client.clone(),
- client,
- inherent_data_providers.clone(),
- )?;
-
- import_setup = Some((block_import, grandpa_link, babe_link));
- Ok(import_queue)
+ let justification_import = grandpa_block_import.clone();
+
+ let (block_import, babe_link) = sc_consensus_babe::block_import(
+ sc_consensus_babe::Config::get_or_compute(&*client)?,
+ grandpa_block_import,
+ client.clone(),
+ )?;
+
+ let import_queue = sc_consensus_babe::import_queue(
+ babe_link.clone(),
+ block_import.clone(),
+ Some(Box::new(justification_import)),
+ None,
+ client,
+ inherent_data_providers.clone(),
+ spawn_task_handle,
+ prometheus_registry,
+ )?;
+
+ import_setup = Some((block_import, grandpa_link, babe_link));
+ Ok(import_queue)
+ },
+ )?
+ .with_rpc_extensions_builder(|builder| {
+ let grandpa_link = import_setup
+ .as_ref()
+ .map(|s| &s.1)
+ .expect("GRANDPA LinkHalf is present for full services or set up failed; qed.");
+
+ let shared_authority_set = grandpa_link.shared_authority_set().clone();
+ let shared_voter_state = grandpa::SharedVoterState::empty();
+
+ rpc_setup = Some((shared_voter_state.clone()));
+
+ let babe_link = import_setup
+ .as_ref()
+ .map(|s| &s.2)
+ .expect("BabeLink is present for full services or set up failed; qed.");
+
+ let babe_config = babe_link.config().clone();
+ let shared_epoch_changes = babe_link.epoch_changes().clone();
+
+ let client = builder.client().clone();
+ let pool = builder.pool().clone();
+ let select_chain = builder
+ .select_chain()
+ .cloned()
+ .expect("SelectChain is present for full services or set up failed; qed.");
+ let keystore = builder.keystore().clone();
+
+ Ok(move |deny_unsafe| {
+ let deps = node_rpc::FullDeps {
+ client: client.clone(),
+ pool: pool.clone(),
+ select_chain: select_chain.clone(),
+ deny_unsafe,
+ babe: node_rpc::BabeDeps {
+ babe_config: babe_config.clone(),
+ shared_epoch_changes: shared_epoch_changes.clone(),
+ keystore: keystore.clone(),
+ },
+ grandpa: node_rpc::GrandpaDeps {
+ shared_voter_state: shared_voter_state.clone(),
+ shared_authority_set: shared_authority_set.clone(),
+ },
+ };
+
+ node_rpc::create_full(deps)
+ })
})?;
- // We don't have any custom rpc commands...
- // .with_rpc_extensions(|client, pool| -> RpcExtension {
- // node_rpc::create(client, pool)
- // })?;
- (builder, import_setup, inherent_data_providers)
+ (builder, import_setup, inherent_data_providers, rpc_setup)
}};
}
@@ -126,58 +160,57 @@ macro_rules! new_full_start {
/// concrete types instead.
macro_rules! new_full {
($config:expr, $with_startup_data: expr) => {{
- use futures::sync::mpsc;
- use network::DhtEvent;
+ use futures::prelude::*;
+ use sc_network::Event;
+ use sc_client_api::ExecutorProvider;
+ use sp_core::traits::BareCryptoStorePtr;
let (
- is_authority,
+ role,
force_authoring,
name,
- disable_grandpa
+ disable_grandpa,
) = (
- $config.roles.is_authority(),
+ $config.role.clone(),
$config.force_authoring,
- $config.name.clone(),
- $config.disable_grandpa
+ $config.network.node_name.clone(),
+ $config.disable_grandpa,
);
- // sentry nodes announce themselves as authorities to the network
- // and should run the same protocols authorities do, but it should
- // never actively participate in any consensus process.
- let participates_in_consensus = is_authority && !$config.sentry_mode;
+ let (builder, mut import_setup, inherent_data_providers, mut rpc_setup) =
+ new_full_start!($config);
- let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
-
- // Dht event channel from the network to the authority discovery module. Use bounded channel to ensure
- // back-pressure. Authority discovery is triggering one event per authority within the current authority set.
- // This estimates the authority set size to be somewhere below 10 000 thereby setting the channel buffer size to
- // 10 000.
- let (dht_event_tx, _dht_event_rx) =
- mpsc::channel::(10_000);
-
- let service = builder.with_network_protocol(|_| Ok(crate::service::NodeProtocol::new()))?
- .with_finality_proof_provider(|client, backend|
- Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _)
- )?
- .with_dht_event_tx(dht_event_tx)?
- .build()?;
+ let service = builder
+ .with_finality_proof_provider(|client, backend| {
+ // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
+ let provider = client as Arc>;
+ Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _)
+ })?
+ .build_full()?;
let (block_import, grandpa_link, babe_link) = import_setup.take()
- .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+ .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+
+ let shared_voter_state = rpc_setup.take()
+ .expect("The SharedVoterState is present for Full Services or setup failed before. qed");
($with_startup_data)(&block_import, &babe_link);
- if participates_in_consensus {
- let proposer = substrate_basic_authorship::ProposerFactory {
- client: service.client(),
- transaction_pool: service.transaction_pool(),
- };
+ if let sc_service::config::Role::Authority { .. } = &role {
+ let proposer = sc_basic_authorship::ProposerFactory::new(
+ service.client(),
+ service.transaction_pool(),
+ service.prometheus_registry().as_ref(),
+ );
let client = service.client();
let select_chain = service.select_chain()
- .ok_or(substrate_service::Error::SelectChainRequired)?;
+ .ok_or(sc_service::Error::SelectChainRequired)?;
+
+ let can_author_with =
+ sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
- let babe_config = babe::BabeParams {
+ let babe_config = sc_consensus_babe::BabeParams {
keystore: service.keystore(),
client,
select_chain,
@@ -187,62 +220,95 @@ macro_rules! new_full {
inherent_data_providers: inherent_data_providers.clone(),
force_authoring,
babe_link,
+ can_author_with,
};
- let babe = babe::start_babe(babe_config)?;
- service.spawn_essential_task(babe);
- }
+ let babe = sc_consensus_babe::start_babe(babe_config)?;
+ service.spawn_essential_task_handle().spawn_blocking("babe-proposer", babe);
+ }
+
+ // Spawn authority discovery module.
+ if matches!(role, sc_service::config::Role::Authority{..} | sc_service::config::Role::Sentry {..}) {
+ let (sentries, authority_discovery_role) = match role {
+ sc_service::config::Role::Authority { ref sentry_nodes } => (
+ sentry_nodes.clone(),
+ sc_authority_discovery::Role::Authority (
+ service.keystore(),
+ ),
+ ),
+ sc_service::config::Role::Sentry {..} => (
+ vec![],
+ sc_authority_discovery::Role::Sentry,
+ ),
+ _ => unreachable!("Due to outer matches! constraint; qed.")
+ };
+
+ let network = service.network();
+ let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move { match e {
+ Event::Dht(e) => Some(e),
+ _ => None,
+ }}).boxed();
+ let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new(
+ service.client(),
+ network,
+ sentries,
+ dht_event_stream,
+ authority_discovery_role,
+ service.prometheus_registry(),
+ );
+
+ service.spawn_task_handle().spawn("authority-discovery", authority_discovery);
+ }
- // if the node isn't actively participating in consensus then it doesn't
+ // if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
- let keystore = if participates_in_consensus {
- Some(service.keystore())
+ let keystore = if role.is_authority() {
+ Some(service.keystore() as BareCryptoStorePtr)
} else {
None
- };
-
- let config = grandpa::Config {
- // FIXME #1578 make this available through chainspec
- gossip_duration: std::time::Duration::from_millis(333),
- justification_period: 512,
- name: Some(name),
- observer_enabled: true,
- keystore,
- is_authority,
- };
-
- match (is_authority, disable_grandpa) {
- (false, false) => {
- // start the lightweight GRANDPA observer
- service.spawn_task(Box::new(grandpa::run_grandpa_observer(
- config,
- grandpa_link,
- service.network(),
- service.on_exit(),
- )?));
- },
- (true, false) => {
- // start the full GRANDPA voter
- let grandpa_config = grandpa::GrandpaParams {
- config,
- link: grandpa_link,
- network: service.network(),
- inherent_data_providers: inherent_data_providers.clone(),
- on_exit: service.on_exit(),
- telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
- voting_rule: grandpa::VotingRulesBuilder::default().build(),
- };
- // the GRANDPA voter task is considered infallible, i.e.
- // if it fails we take down the service with it.
- service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)?);
- },
- (_, true) => {
- grandpa::setup_disabled_grandpa(
- service.client(),
- &inherent_data_providers,
- service.network(),
- )?;
- },
+ };
+
+ let config = grandpa::Config {
+ // FIXME #1578 make this available through chainspec
+ gossip_duration: std::time::Duration::from_millis(333),
+ justification_period: 512,
+ name: Some(name),
+ observer_enabled: false,
+ keystore,
+ is_authority: role.is_network_authority(),
+ };
+
+ let enable_grandpa = !disable_grandpa;
+ if enable_grandpa {
+ // start the full GRANDPA voter
+ // NOTE: non-authorities could run the GRANDPA observer protocol, but at
+ // this point the full voter should provide better guarantees of block
+ // and vote data availability than the observer. The observer has not
+ // been tested extensively yet and having most nodes in a network run it
+ // could lead to finality stalls.
+ let grandpa_config = grandpa::GrandpaParams {
+ config,
+ link: grandpa_link,
+ network: service.network(),
+ inherent_data_providers: inherent_data_providers.clone(),
+ telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
+ voting_rule: grandpa::VotingRulesBuilder::default().build(),
+ prometheus_registry: service.prometheus_registry(),
+ shared_voter_state,
+ };
+
+ // the GRANDPA voter task is considered infallible, i.e.
+ // if it fails we take down the service with it.
+ service.spawn_essential_task_handle().spawn_blocking(
+ "grandpa-voter",
+ grandpa::run_grandpa_voter(grandpa_config)?
+ );
+ } else {
+ grandpa::setup_disabled_grandpa(
+ service.client(),
+ &inherent_data_providers,
+ service.network(),
+ )?;
}
Ok((service, inherent_data_providers))
@@ -252,70 +318,49 @@ macro_rules! new_full {
}}
}
-#[allow(dead_code)]
-type ConcreteBlock = node_runtime::opaque::Block;
-#[allow(dead_code)]
-type ConcreteClient = Client<
- Backend,
- LocalCallExecutor, NativeExecutor>,
- ConcreteBlock,
- node_runtime::RuntimeApi,
->;
-#[allow(dead_code)]
-type ConcreteBackend = Backend;
-
-/// A specialized configuration object for setting up the node..
-pub type NodeConfiguration =
- Configuration;
-
/// Builds a new service for a full client.
-pub fn new_full(config: NodeConfiguration)
--> Result<
- Service<
- ConcreteBlock,
- ConcreteClient,
- LongestChain,
- NetworkStatus,
- NetworkService::Hash>,
- TransactionPool>,
- OffchainWorkers<
- ConcreteClient,
- >::OffchainStorage,
- ConcreteBlock,
- >
- >,
- ServiceError,
->
-{
+pub fn new_full(config: Configuration) -> Result {
new_full!(config).map(|(service, _)| service)
}
/// Builds a new service for a light client.
-pub fn new_light(
- config: NodeConfiguration,
-) -> Result {
- // type RpcExtension = jsonrpc_core::IoHandler;
+pub fn new_light(config: Configuration) -> Result {
let inherent_data_providers = InherentDataProviders::new();
- let service = ServiceBuilder::new_light::(config)?
+ let service = ServiceBuilder::new_light::(config)?
.with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))?
- .with_transaction_pool(|config, client| {
- Ok(TransactionPool::new(
- config,
- transaction_pool::FullChainApi::new(client),
- ))
+ .with_transaction_pool(|builder| {
+ let fetcher = builder
+ .fetcher()
+ .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
+ let pool_api =
+ sc_transaction_pool::LightChainApi::new(builder.client().clone(), fetcher);
+ let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
+ builder.config().transaction_pool.clone(),
+ Arc::new(pool_api),
+ builder.prometheus_registry(),
+ sc_transaction_pool::RevalidationType::Light,
+ );
+ Ok(pool)
})?
.with_import_queue_and_fprb(
- |_config, client, backend, fetcher, _select_chain, _tx_pool| {
+ |_config,
+ client,
+ backend,
+ fetcher,
+ _select_chain,
+ _tx_pool,
+ spawn_task_handle,
+ registry| {
let fetch_checker = fetcher
.map(|fetcher| fetcher.checker().clone())
.ok_or_else(|| {
"Trying to start light import queue without active fetch checker"
})?;
- let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi>(
+ let grandpa_block_import = grandpa::light_block_import(
client.clone(),
backend,
- &*client,
+ &(client.clone() as Arc<_>),
Arc::new(fetch_checker),
)?;
@@ -323,35 +368,294 @@ pub fn new_light(
let finality_proof_request_builder =
finality_proof_import.create_finality_proof_request_builder();
- let (babe_block_import, babe_link) = babe::block_import(
- babe::Config::get_or_compute(&*client)?,
+ let (babe_block_import, babe_link) = sc_consensus_babe::block_import(
+ sc_consensus_babe::Config::get_or_compute(&*client)?,
grandpa_block_import,
client.clone(),
- client.clone(),
)?;
- let import_queue = babe::import_queue(
+ let import_queue = sc_consensus_babe::import_queue(
babe_link,
babe_block_import,
None,
Some(Box::new(finality_proof_import)),
- client.clone(),
client,
inherent_data_providers.clone(),
+ spawn_task_handle,
+ registry,
)?;
Ok((import_queue, finality_proof_request_builder))
},
)?
- .with_network_protocol(|_| Ok(NodeProtocol::new()))?
.with_finality_proof_provider(|client, backend| {
- Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _)
+ // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
+ let provider = client as Arc>;
+ Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
+ })?
+ .with_rpc_extensions(|builder| {
+ let fetcher = builder
+ .fetcher()
+ .ok_or_else(|| "Trying to start node RPC without active fetcher")?;
+ let remote_blockchain = builder
+ .remote_backend()
+ .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
+
+ let light_deps = node_rpc::LightDeps {
+ remote_blockchain,
+ fetcher,
+ client: builder.client().clone(),
+ pool: builder.pool(),
+ };
+
+ Ok(node_rpc::create_light(light_deps))
})?
- // We don't have any custom rpc extensions
- // .with_rpc_extensions(|client, pool| -> RpcExtension {
- // node_rpc::create(client, pool)
- // })?
- .build()?;
+ .build_light()?;
Ok(service)
}
+
+#[cfg(test)]
+mod tests {
+ use crate::node_executor;
+ use crate::node_rpc;
+ use crate::service::{new_full, new_light};
+ use codec::{Decode, Encode};
+ use node_runtime::RuntimeApi;
+ use node_runtime::{currency::CENTS, SLOT_DURATION};
+ use node_runtime::{opaque::Block, AccountId, DigestItem, Signature};
+ use node_runtime::{BalancesCall, Call, UncheckedExtrinsic};
+ use sc_consensus_babe::{BabeIntermediate, CompatibleDigestItem, INTERMEDIATE_KEY};
+ use sc_consensus_epochs::descendent_query;
+ use sc_finality_grandpa::{self as grandpa};
+ use sc_service::AbstractService;
+ use sp_consensus::{
+ BlockImport, BlockImportParams, BlockOrigin, Environment, ForkChoiceStrategy, Proposer,
+ RecordProof,
+ };
+ use sp_core::{crypto::Pair as CryptoPair, H256};
+ use sp_finality_tracker;
+ use sp_keyring::AccountKeyring;
+ use sp_runtime::traits::IdentifyAccount;
+ use sp_runtime::{
+ generic::{BlockId, Digest, Era, SignedPayload},
+ traits::Verify,
+ traits::{Block as BlockT, Header as HeaderT},
+ OpaqueExtrinsic,
+ };
+ use sp_timestamp;
+ use sp_transaction_pool::{ChainEvent, MaintainedTransactionPool};
+ use std::{any::Any, borrow::Cow, sync::Arc};
+
+ type AccountPublic = ::Signer;
+
+ // Long running test. Run it locally only after the node changes.
+ #[test]
+ // It is "ignored", but the node-cli ignored tests are running on the CI.
+ // This can be run locally with `cargo test --release -p node-cli test_sync -- --ignored`.
+ #[ignore]
+ fn test_sync() {
+ let keystore_path = tempfile::tempdir().expect("Creates keystore path");
+ let keystore =
+ sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore");
+ let alice = keystore
+ .write()
+ .insert_ephemeral_from_seed::("//Alice")
+ .expect("Creates authority pair");
+
+ let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority();
+
+ // For the block factory
+ let mut slot_num = 1u64;
+
+ // For the extrinsics factory
+ let bob = Arc::new(AccountKeyring::Bob.pair());
+ let charlie = Arc::new(AccountKeyring::Charlie.pair());
+ let mut index = 0;
+
+ sc_service_test::sync(
+ chain_spec,
+ |config| {
+ let mut setup_handles = None;
+ new_full!(
+ config,
+ |block_import: &sc_consensus_babe::BabeBlockImport,
+ babe_link: &sc_consensus_babe::BabeLink| {
+ setup_handles = Some((block_import.clone(), babe_link.clone()));
+ }
+ )
+ .map(move |(node, x)| (node, (x, setup_handles.unwrap())))
+ },
+ |config| new_light(config),
+ |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| {
+ let mut inherent_data = inherent_data_providers
+ .create_inherent_data()
+ .expect("Creates inherent data.");
+ inherent_data.replace_data(sp_finality_tracker::INHERENT_IDENTIFIER, &1u64);
+
+ let parent_id = BlockId::number(service.client().chain_info().best_number);
+ let parent_header = service.client().header(&parent_id).unwrap().unwrap();
+ let parent_hash = parent_header.hash();
+ let parent_number = *parent_header.number();
+
+ futures::executor::block_on(service.transaction_pool().maintain(
+ ChainEvent::NewBlock {
+ is_new_best: true,
+ hash: parent_header.hash(),
+ tree_route: None,
+ header: parent_header.clone(),
+ },
+ ));
+
+ let mut proposer_factory = sc_basic_authorship::ProposerFactory::new(
+ service.client(),
+ service.transaction_pool(),
+ None,
+ );
+
+ let epoch_descriptor = babe_link
+ .epoch_changes()
+ .lock()
+ .epoch_descriptor_for_child_of(
+ descendent_query(&*service.client()),
+ &parent_hash,
+ parent_number,
+ slot_num,
+ )
+ .unwrap()
+ .unwrap();
+
+ let mut digest = Digest::::default();
+
+ // even though there's only one authority some slots might be empty,
+ // so we must keep trying the next slots until we can claim one.
+ let babe_pre_digest = loop {
+ inherent_data.replace_data(
+ sp_timestamp::INHERENT_IDENTIFIER,
+ &(slot_num * SLOT_DURATION),
+ );
+ if let Some(babe_pre_digest) = sc_consensus_babe::test_helpers::claim_slot(
+ slot_num,
+ &parent_header,
+ &*service.client(),
+ &keystore,
+ &babe_link,
+ ) {
+ break babe_pre_digest;
+ }
+
+ slot_num += 1;
+ };
+
+ digest.push(::babe_pre_digest(
+ babe_pre_digest,
+ ));
+
+ let new_block = futures::executor::block_on(async move {
+ let proposer = proposer_factory.init(&parent_header).await;
+ proposer
+ .unwrap()
+ .propose(
+ inherent_data,
+ digest,
+ std::time::Duration::from_secs(1),
+ RecordProof::Yes,
+ )
+ .await
+ })
+ .expect("Error making test block")
+ .block;
+
+ let (new_header, new_body) = new_block.deconstruct();
+ let pre_hash = new_header.hash();
+ // sign the pre-sealed hash of the block and then
+ // add it to a digest item.
+ let to_sign = pre_hash.encode();
+ let signature = alice.sign(&to_sign[..]);
+ let item = ::babe_seal(signature.into());
+ slot_num += 1;
+
+ let mut params = BlockImportParams::new(BlockOrigin::File, new_header);
+ params.post_digests.push(item);
+ params.body = Some(new_body);
+ params.intermediates.insert(
+ Cow::from(INTERMEDIATE_KEY),
+ Box::new(BabeIntermediate:: { epoch_descriptor }) as Box,
+ );
+ params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
+
+ block_import
+ .import_block(params, Default::default())
+ .expect("error importing test block");
+ },
+ |service, _| {
+ let amount = 5 * CENTS;
+ let to: AccountId = AccountPublic::from(bob.public()).into_account().into();
+ let from: AccountId = AccountPublic::from(charlie.public()).into_account().into();
+ let genesis_hash = service.client().block_hash(0).unwrap().unwrap();
+ let best_block_id = BlockId::number(service.client().chain_info().best_number);
+ let (spec_version, transaction_version) = {
+ let version = service.client().runtime_version_at(&best_block_id).unwrap();
+ (version.spec_version, version.transaction_version)
+ };
+ let signer = charlie.clone();
+
+ let function = Call::Balances(BalancesCall::transfer(to.into(), amount));
+
+ let check_spec_version = frame_system::CheckSpecVersion::new();
+ let check_tx_version = frame_system::CheckTxVersion::new();
+ let check_genesis = frame_system::CheckGenesis::new();
+ let check_era = frame_system::CheckEra::from(Era::Immortal);
+ let check_nonce = frame_system::CheckNonce::from(index);
+ let check_weight = frame_system::CheckWeight::new();
+ let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0);
+ let validate_grandpa_equivocation =
+ pallet_grandpa::ValidateEquivocationReport::new();
+ let extra = (
+ check_spec_version,
+ check_tx_version,
+ check_genesis,
+ check_era,
+ check_nonce,
+ check_weight,
+ payment,
+ validate_grandpa_equivocation,
+ );
+ let raw_payload = SignedPayload::from_raw(
+ function,
+ extra,
+ (
+ spec_version,
+ transaction_version,
+ genesis_hash,
+ genesis_hash,
+ (),
+ (),
+ (),
+ (),
+ ),
+ );
+ let signature = raw_payload.using_encoded(|payload| signer.sign(payload));
+ let (function, extra, _) = raw_payload.deconstruct();
+ let xt =
+ UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), extra)
+ .encode();
+ let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap();
+
+ index += 1;
+ OpaqueExtrinsic(v)
+ },
+ );
+ }
+
+ #[test]
+ #[ignore]
+ fn test_consensus() {
+ sc_service_test::consensus(
+ crate::chain_spec::tests::integration_test_config_with_two_authorities(),
+ |config| new_full(config),
+ |config| new_light(config),
+ vec!["//Alice".into(), "//Bob".into()],
+ )
+ }
+}
diff --git a/runtime-modules/proposals/codex/src/tests/mock.rs b/runtime-modules/proposals/codex/src/tests/mock.rs
index ccef3b3a10..071e58a4ba 100644
--- a/runtime-modules/proposals/codex/src/tests/mock.rs
+++ b/runtime-modules/proposals/codex/src/tests/mock.rs
@@ -230,29 +230,6 @@ where
pub type Extrinsic = TestXt;
-/*
- type Currency = Balances;
- type UnixTime = Timestamp;
- type CurrencyToVote = CurrencyToVoteHandler;
- type RewardRemainder = RewardRemainderMock;
- type Event = MetaEvent;
- type Slash = ();
- type Reward = ();
- type SessionsPerEra = SessionsPerEra;
- type SlashDeferDuration = SlashDeferDuration;
- type SlashCancelOrigin = frame_system::EnsureRoot;
- type BondingDuration = BondingDuration;
- type SessionInterface = Self;
- type RewardCurve = RewardCurve;
- type NextNewSession = Session;
- type ElectionLookahead = ElectionLookahead;
- type Call = Call;
- type MaxIterations = MaxIterations;
- type MinSolutionScoreBump = MinSolutionScoreBump;
- type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
- type UnsignedPriority = UnsignedPriority;
-*/
-
impl staking::SessionInterface for Test {
fn disable_validator(_: &u64) -> Result {
unimplemented!()
diff --git a/runtime-modules/working-group/src/lib.rs b/runtime-modules/working-group/src/lib.rs
index e057b7a575..d4206a67c5 100644
--- a/runtime-modules/working-group/src/lib.rs
+++ b/runtime-modules/working-group/src/lib.rs
@@ -1475,7 +1475,8 @@ impl, I: Instance> Module {
Ok(())
}
- fn initialize_working_group(
+ // Initialize working group constraints and mint.
+ pub(crate) fn initialize_working_group(
opening_human_readable_text_constraint: InputValidationLengthConstraint,
worker_application_human_readable_text_constraint: InputValidationLengthConstraint,
worker_exit_rationale_text_constraint: InputValidationLengthConstraint,
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 6aabcf1749..80298d58ae 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -25,7 +25,7 @@ sp-block-builder = { package = 'sp-block-builder', default-features = false, git
sp-api = { package = 'sp-api', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
sp-version = { package = 'sp-version', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
sp-staking = { package = 'sp-staking', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
-node-primitives = { package = 'node-primitives', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+sp-application-crypto = { package = 'sp-application-crypto', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
# Frame
frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
@@ -37,7 +37,6 @@ system = { package = 'frame-system', default-features = false, git = 'https://gi
pallet-grandpa = { package = 'pallet-grandpa', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-staking-reward-curve = { package = 'pallet-staking-reward-curve', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-babe = { package = 'pallet-babe', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
-pallet-indices = { package = 'pallet-indices', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-transaction-payment = { package = 'pallet-transaction-payment', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-transaction-payment-rpc-runtime-api = { package = 'pallet-transaction-payment-rpc-runtime-api', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-authorship = { package = 'pallet-authorship', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
@@ -52,6 +51,15 @@ pallet-timestamp = { package = 'pallet-timestamp', default-features = false, git
pallet-balances = { package = 'pallet-balances', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-im-online = { package = 'pallet-im-online', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
pallet-collective = { package = 'pallet-collective', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+pallet-contracts = { package = 'pallet-contracts', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+pallet-contracts-rpc-runtime-api = { package = 'pallet-contracts-rpc-runtime-api', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+pallet-contracts-primitives = { package = 'pallet-contracts-primitives', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+
+# Benchmarking
+frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', default-features = false, optional = true }
+frame-system-benchmarking = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', default-features = false, optional = true }
+pallet-offences-benchmarking = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', default-features = false, optional = true }
+pallet-session-benchmarking = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', default-features = false, optional = true }
# Joystream
common = { package = 'pallet-common', default-features = false, path = '../runtime-modules/common'}
@@ -101,7 +109,7 @@ std = [
'sp-block-builder/std',
'sp-session/std',
'sp-staking/std',
- 'node-primitives/std',
+ 'sp-application-crypto/std',
# Frame
'frame-support/std',
@@ -124,10 +132,12 @@ std = [
'pallet-staking/std',
# 'pallet-staking-reward-curve/std', // don't have 'std' features
'pallet-sudo/std',
- 'pallet-indices/std',
'pallet-im-online/std',
'pallet-collective/std',
'pallet-offences/std',
+ 'pallet-contracts/std',
+ 'pallet-contracts-rpc-runtime-api/std',
+ 'pallet-contracts-primitives/std',
# Joystream
'common/std',
@@ -149,6 +159,19 @@ std = [
'proposals-discussion/std',
'proposals-codex/std',
]
-
+runtime-benchmarks = [
+ "system/runtime-benchmarks",
+ "frame-support/runtime-benchmarks",
+ "sp-runtime/runtime-benchmarks",
+ "pallet-balances/runtime-benchmarks",
+ "pallet-collective/runtime-benchmarks",
+ "pallet-im-online/runtime-benchmarks",
+ "pallet-staking/runtime-benchmarks",
+ "pallet-timestamp/runtime-benchmarks",
+ "frame-benchmarking",
+ "frame-system-benchmarking",
+ "pallet-offences-benchmarking",
+ "pallet-session-benchmarking",
+]
diff --git a/runtime/src/constants.rs b/runtime/src/constants.rs
new file mode 100644
index 0000000000..b6c32ae829
--- /dev/null
+++ b/runtime/src/constants.rs
@@ -0,0 +1,49 @@
+use crate::{BlockNumber, Moment};
+
+/// Constants for Babe.
+
+/// Since BABE is probabilistic this is the average expected block time that
+/// we are targetting. Blocks will be produced at a minimum duration defined
+/// by `SLOT_DURATION`, but some slots will not be allocated to any
+/// authority and hence no block will be produced. We expect to have this
+/// block time on average following the defined slot duration and the value
+/// of `c` configured for BABE (where `1 - c` represents the probability of
+/// a slot being empty).
+/// This value is only used indirectly to define the unit constants below
+/// that are expressed in blocks. The rest of the code should use
+/// `SLOT_DURATION` instead (like the timestamp module for calculating the
+/// minimum period).
+///
+pub const MILLISECS_PER_BLOCK: Moment = 6000;
+pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000;
+
+pub const SLOT_DURATION: Moment = 6000;
+
+pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES;
+pub const EPOCH_DURATION_IN_SLOTS: u64 = {
+ const SLOT_FILL_RATE: f64 = MILLISECS_PER_BLOCK as f64 / SLOT_DURATION as f64;
+
+ (EPOCH_DURATION_IN_BLOCKS as f64 * SLOT_FILL_RATE) as u64
+};
+
+// These time units are defined in number of blocks.
+pub const MINUTES: BlockNumber = 60 / (SECS_PER_BLOCK as BlockNumber);
+pub const HOURS: BlockNumber = MINUTES * 60;
+pub const DAYS: BlockNumber = HOURS * 24;
+
+// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
+pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
+
+/// Tests only
+#[cfg(any(feature = "std", test))]
+pub mod currency {
+ use crate::primitives::Balance;
+
+ pub const MILLICENTS: Balance = 1_000_000_000;
+ pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent.
+ pub const DOLLARS: Balance = 100 * CENTS;
+
+ pub const fn deposit(items: u32, bytes: u32) -> Balance {
+ items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS
+ }
+}
diff --git a/runtime/src/integration/mod.rs b/runtime/src/integration/mod.rs
index 592b56f838..35774a7c6c 100644
--- a/runtime/src/integration/mod.rs
+++ b/runtime/src/integration/mod.rs
@@ -2,5 +2,6 @@ pub mod content_working_group;
pub mod forum;
pub mod proposals;
pub mod storage;
+pub mod transactions;
pub mod versioned_store_permissions;
pub mod working_group;
diff --git a/runtime/src/integration/transactions.rs b/runtime/src/integration/transactions.rs
new file mode 100644
index 0000000000..865e09bd2f
--- /dev/null
+++ b/runtime/src/integration/transactions.rs
@@ -0,0 +1,69 @@
+use codec::Encode;
+use frame_support::debug;
+use frame_support::weights::{WeightToFeeCoefficients, WeightToFeePolynomial};
+use sp_runtime::generic;
+use sp_runtime::generic::SignedPayload;
+use sp_runtime::SaturatedConversion;
+
+use crate::{AccountId, Balance, BlockHashCount, Index, SignedExtra, UncheckedExtrinsic};
+use crate::{Call, Runtime, System};
+
+/// Stub for zero transaction weights.
+pub struct NoWeights;
+impl WeightToFeePolynomial for NoWeights {
+ type Balance = Balance;
+
+ fn polynomial() -> WeightToFeeCoefficients {
+ Default::default()
+ }
+
+ fn calc(_weight: &u64) -> Self::Balance {
+ Default::default()
+ }
+}
+
+/// 'Create transaction' default implementation.
+pub(crate) fn create_transaction<
+ C: system::offchain::AppCrypto<
+ ::Public,
+ ::Signature,
+ >,
+>(
+ call: Call,
+ public: <::Signature as sp_runtime::traits::Verify>::Signer,
+ account: AccountId,
+ nonce: Index,
+) -> Option<(
+ Call,
+ ::SignaturePayload,
+)> {
+ // take the biggest period possible.
+ let period = BlockHashCount::get()
+ .checked_next_power_of_two()
+ .map(|c| c / 2)
+ .unwrap_or(2) as u64;
+ let current_block = System::block_number()
+ .saturated_into::()
+ // The `System::block_number` is initialized with `n+1`,
+ // so the actual block number is `n`.
+ .saturating_sub(1);
+ let tip = 0;
+ let extra: SignedExtra = (
+ system::CheckSpecVersion::::new(),
+ system::CheckTxVersion::::new(),
+ system::CheckGenesis::::new(),
+ system::CheckEra::::from(generic::Era::mortal(period, current_block)),
+ system::CheckNonce::::from(nonce),
+ system::CheckWeight::::new(),
+ pallet_transaction_payment::ChargeTransactionPayment::::from(tip),
+ pallet_grandpa::ValidateEquivocationReport::::new(),
+ );
+ let raw_payload = SignedPayload::new(call, extra)
+ .map_err(|e| {
+ debug::warn!("Unable to create signed payload: {:?}", e);
+ })
+ .ok()?;
+ let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
+ let (call, extra, _) = raw_payload.deconstruct();
+ Some((call, (account, signature, extra)))
+}
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index ffd592fb01..e89630bdc0 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -13,39 +13,27 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
+mod constants;
mod integration;
-mod migration;
+mod primitives;
+mod runtime_api;
#[cfg(test)]
mod tests; // Runtime integration tests
-use codec::Encode;
-use frame_support::inherent::{CheckInherentsResult, InherentData};
use frame_support::traits::KeyOwnerProofSystem;
use frame_support::weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
- IdentityFee, Weight,
+ Weight,
};
-use frame_support::{construct_runtime, debug, parameter_types, traits::Randomness};
-use pallet_grandpa::fg_primitives;
+use frame_support::{construct_runtime, parameter_types};
use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_session::historical as pallet_session_historical;
-use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
-use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
-use sp_api::impl_runtime_apis;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_core::crypto::KeyTypeId;
-use sp_core::OpaqueMetadata;
use sp_runtime::curve::PiecewiseLinear;
-use sp_runtime::generic::SignedPayload;
-use sp_runtime::traits::{
- BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, Saturating, StaticLookup, Verify,
-};
-use sp_runtime::transaction_validity::{TransactionSource, TransactionValidity};
-use sp_runtime::{
- create_runtime_str, generic, impl_opaque_keys, ApplyExtrinsicResult, FixedPointNumber,
- MultiSignature, Perbill, Perquintill, SaturatedConversion,
-};
+use sp_runtime::traits::{BlakeTwo256, Block as BlockT, IdentityLookup, OpaqueKeys, Saturating};
+use sp_runtime::{create_runtime_str, generic, impl_opaque_keys, Perbill};
use sp_std::boxed::Box;
use sp_std::vec::Vec;
#[cfg(feature = "std")]
@@ -53,88 +41,26 @@ use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use system::EnsureRoot;
+pub use constants::*;
+pub use primitives::*;
+pub use runtime_api::*;
+
use integration::proposals::{CouncilManager, ExtrinsicProposalEncoder, MembershipOriginValidator};
use content_working_group as content_wg;
use governance::{council, election};
use storage::{data_directory, data_object_storage_registry, data_object_type_registry};
-/// Priority for a transaction. Additive. Higher is better.
-pub type TransactionPriority = u64;
-
-/// Alias for ContentId, used in various places.
-pub type ContentId = sp_core::H256;
-
-/// An index to a block.
-pub type BlockNumber = u32;
-
-/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
-pub type Signature = MultiSignature;
-
-/// Some way of identifying an account on the chain. We intentionally make it equivalent
-/// to the public key of our transaction signing scheme.
-pub type AccountId = <::Signer as IdentifyAccount>::AccountId;
-
-/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
-/// never know...
-pub type AccountIndex = u32;
-
-/// Balance of an account.
-pub type Balance = u128;
-
-/// Index of a transaction in the chain.
-pub type Index = u32;
-
-/// A hash of some data used by the chain.
-pub type Hash = sp_core::H256;
-
-/// Moment type
-pub type Moment = u64;
-
-/// Credential type
-pub type Credential = u64;
-
-/// Represents a thread identifier for both Forum and Proposals Discussion
-///
-/// Note: Both modules expose type names ThreadId and PostId (which are defined on their Trait) and
-/// used in state storage and dispatchable method's argument types,
-/// and are therefore part of the public API/metadata of the runtime.
-/// In the current version the polkadot-js/api that is used and is compatible with the runtime,
-/// the type registry has flat namespace and its not possible
-/// to register identically named types from different modules, separately. And so we MUST configure
-/// the underlying types to be identicaly to avoid issues with encoding/decoding these types on the client side.
-pub type ThreadId = u64;
-
-/// Represents a post identifier for both Forum and Proposals Discussion
-///
-/// See the Note about ThreadId
-pub type PostId = u64;
-
-/// Represent an actor in membership group, which is the same in the working groups.
-pub type ActorId = u64;
-
-/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
-/// the specifics of the runtime. They can then be made to be agnostic over specific formats
-/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
-/// to even the core data structures.
-pub mod opaque {
- use super::*;
-
- pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
-
- pub type Header = generic::Header;
- pub type Block = generic::Block;
- pub type BlockId = generic::BlockId;
- pub type SessionHandlers = (Grandpa, Babe, ImOnline);
-
- impl_opaque_keys! {
- pub struct SessionKeys {
- pub grandpa: Grandpa,
- pub babe: Babe,
- pub im_online: ImOnline,
- }
- }
-}
+// Node dependencies
+pub use common;
+pub use forum;
+pub use governance::election_params::ElectionParameters;
+#[cfg(any(feature = "std", test))]
+pub use pallet_balances::Call as BalancesCall;
+pub use pallet_staking::StakerStatus;
+pub use proposals_codex::ProposalsConfigParameters;
+pub use versioned_store;
+pub use working_group;
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
@@ -143,44 +69,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
authoring_version: 7,
spec_version: 0,
impl_version: 0,
- apis: RUNTIME_API_VERSIONS,
+ apis: crate::runtime_api::EXPORTED_RUNTIME_API_VERSIONS,
transaction_version: 1,
};
-/// Constants for Babe.
-
-/// Since BABE is probabilistic this is the average expected block time that
-/// we are targetting. Blocks will be produced at a minimum duration defined
-/// by `SLOT_DURATION`, but some slots will not be allocated to any
-/// authority and hence no block will be produced. We expect to have this
-/// block time on average following the defined slot duration and the value
-/// of `c` configured for BABE (where `1 - c` represents the probability of
-/// a slot being empty).
-/// This value is only used indirectly to define the unit constants below
-/// that are expressed in blocks. The rest of the code should use
-/// `SLOT_DURATION` instead (like the timestamp module for calculating the
-/// minimum period).
-///
-pub const MILLISECS_PER_BLOCK: Moment = 6000;
-pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000;
-
-pub const SLOT_DURATION: Moment = 6000;
-
-pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES;
-pub const EPOCH_DURATION_IN_SLOTS: u64 = {
- const SLOT_FILL_RATE: f64 = MILLISECS_PER_BLOCK as f64 / SLOT_DURATION as f64;
-
- (EPOCH_DURATION_IN_BLOCKS as f64 * SLOT_FILL_RATE) as u64
-};
-
-// These time units are defined in number of blocks.
-pub const MINUTES: BlockNumber = 60 / (SECS_PER_BLOCK as BlockNumber);
-pub const HOURS: BlockNumber = MINUTES * 60;
-pub const DAYS: BlockNumber = HOURS * 24;
-
-// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
-pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
-
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
@@ -214,7 +106,7 @@ impl system::Trait for Runtime {
type Hash = Hash;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
- type Lookup = Indices;
+ type Lookup = IdentityLookup;
type Header = generic::Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
@@ -258,7 +150,7 @@ impl pallet_grandpa::Trait for Runtime {
type HandleEquivocation = pallet_grandpa::EquivocationHandler<
Self::KeyOwnerIdentification,
- node_primitives::report::ReporterAppCrypto,
+ primitives::report::ReporterAppCrypto,
Runtime,
Offences,
>;
@@ -277,36 +169,7 @@ where
Call,
::SignaturePayload,
)> {
- // take the biggest period possible.
- let period = BlockHashCount::get()
- .checked_next_power_of_two()
- .map(|c| c / 2)
- .unwrap_or(2) as u64;
- let current_block = System::block_number()
- .saturated_into::()
- // The `System::block_number` is initialized with `n+1`,
- // so the actual block number is `n`.
- .saturating_sub(1);
- let tip = 0;
- let extra: SignedExtra = (
- system::CheckSpecVersion::::new(),
- system::CheckTxVersion::::new(),
- system::CheckGenesis::::new(),
- system::CheckEra::::from(generic::Era::mortal(period, current_block)),
- system::CheckNonce::::from(nonce),
- system::CheckWeight::::new(),
- pallet_transaction_payment::ChargeTransactionPayment::::from(tip),
- pallet_grandpa::ValidateEquivocationReport::::new(),
- );
- let raw_payload = SignedPayload::new(call, extra)
- .map_err(|e| {
- debug::warn!("Unable to create signed payload: {:?}", e);
- })
- .ok()?;
- let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
- let address = Indices::unlookup(account);
- let (call, extra, _) = raw_payload.deconstruct();
- Some((call, (address, signature, extra)))
+ integration::transactions::create_transaction::(call, public, account, nonce)
}
}
@@ -323,17 +186,6 @@ where
type OverarchingCall = Call;
}
-parameter_types! {
- pub const IndexDeposit: Balance = 0; // no minimum deposit
-}
-
-impl pallet_indices::Trait for Runtime {
- type AccountIndex = AccountIndex;
- type Currency = Balances;
- type Deposit = IndexDeposit;
- type Event = Event;
-}
-
parameter_types! {
pub const MinimumPeriod: Moment = SLOT_DURATION / 2;
}
@@ -360,19 +212,15 @@ impl pallet_balances::Trait for Runtime {
}
parameter_types! {
- pub const TransactionByteFee: Balance = 1; // TODO: adjust fee
- pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
- pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000);
- pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128);
+ pub const TransactionByteFee: Balance = 0; // TODO: adjust fee
}
impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = ();
type TransactionByteFee = TransactionByteFee;
- type WeightToFee = IdentityFee; // TODO: adjust weight
- type FeeMultiplierUpdate =
- TargetedFeeAdjustment;
+ type WeightToFee = integration::transactions::NoWeights; // TODO: adjust weight
+ type FeeMultiplierUpdate = (); // TODO: adjust fee
}
impl pallet_sudo::Trait for Runtime {
@@ -391,16 +239,14 @@ impl pallet_authorship::Trait for Runtime {
type EventHandler = Staking;
}
-type SessionHandlers = (Grandpa, Babe, ImOnline);
-
impl_opaque_keys! {
pub struct SessionKeys {
pub grandpa: Grandpa,
pub babe: Babe,
pub im_online: ImOnline,
+ pub authority_discovery: AuthorityDiscovery,
}
}
-
// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler.
// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in
// `SessionKeys`.
@@ -417,7 +263,7 @@ impl pallet_session::Trait for Runtime {
type ShouldEndSession = Babe;
type NextSessionRotation = Babe;
type SessionManager = pallet_session::historical::NoteHistoricalRoot;
- type SessionHandler = SessionHandlers;
+ type SessionHandler = ::KeyTypeIdProviders;
type Keys = SessionKeys;
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
}
@@ -623,9 +469,6 @@ impl forum::Trait for Runtime {
type PostId = PostId;
}
-impl migration::Trait for Runtime {
- type Event = Event;
-}
// The storage working group instance alias.
pub type StorageWorkingGroupInstance = working_group::Instance2;
@@ -700,6 +543,49 @@ impl proposals_codex::Trait for Runtime {
type ProposalEncoder = ExtrinsicProposalEncoder;
}
+parameter_types! {
+ pub const TombstoneDeposit: Balance = 1; // TODO: adjust fee
+ pub const RentByteFee: Balance = 1; // TODO: adjust fee
+ pub const RentDepositOffset: Balance = 0; // no rent deposit
+ pub const SurchargeReward: Balance = 0; // no reward
+}
+
+impl pallet_contracts::Trait for Runtime {
+ type Time = Timestamp;
+ type Randomness = RandomnessCollectiveFlip;
+ type Currency = Balances;
+ type Event = Event;
+ type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer;
+ type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter;
+ type RentPayment = ();
+ type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;
+ type TombstoneDeposit = TombstoneDeposit;
+ type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;
+ type RentByteFee = RentByteFee;
+ type RentDepositOffset = RentDepositOffset;
+ type SurchargeReward = SurchargeReward;
+ type MaxDepth = pallet_contracts::DefaultMaxDepth;
+ type MaxValueSize = pallet_contracts::DefaultMaxValueSize;
+ type WeightPrice = pallet_transaction_payment::Module;
+}
+
+/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
+/// the specifics of the runtime. They can then be made to be agnostic over specific formats
+/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
+/// to even the core datastructures.
+pub mod opaque {
+ use super::*;
+
+ pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
+
+ /// Opaque block header type.
+ pub type Header = generic::Header;
+ /// Opaque block type.
+ pub type Block = generic::Block;
+ /// Opaque block identifier type.
+ pub type BlockId = generic::BlockId;
+}
+
construct_runtime!(
pub enum Runtime where
Block = Block,
@@ -711,7 +597,6 @@ construct_runtime!(
Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
Authorship: pallet_authorship::{Module, Call, Storage, Inherent},
- Indices: pallet_indices::{Module, Call, Storage, Config, Event},
Balances: pallet_balances::{Module, Call, Storage, Config, Event},
TransactionPayment: pallet_transaction_payment::{Module, Storage},
Staking: pallet_staking::{Module, Call, Config, Storage, Event, ValidateUnsigned},
@@ -724,8 +609,8 @@ construct_runtime!(
Offences: pallet_offences::{Module, Call, Storage, Event},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
Sudo: pallet_sudo::{Module, Call, Config, Storage, Event},
+ Contracts: pallet_contracts::{Module, Call, Config, Storage, Event},
// Joystream
- Migration: migration::{Module, Call, Storage, Event, Config},
CouncilElection: election::{Module, Call, Storage, Event, Config},
Council: council::{Module, Call, Storage, Event, Config},
Memo: memo::{Module, Call, Storage, Event},
@@ -752,177 +637,3 @@ construct_runtime!(
StorageWorkingGroup: working_group::::{Module, Call, Storage, Config, Event},
}
);
-
-/// The address format for describing accounts.
-pub type Address = ::Source;
-/// Block header type as expected by this runtime.
-pub type Header = generic::Header;
-/// Block type as expected by this runtime.
-pub type Block = generic::Block;
-/// A Block signed with a Justification
-pub type SignedBlock = generic::SignedBlock;
-/// BlockId type as expected by this runtime.
-pub type BlockId = generic::BlockId;
-/// The SignedExtension to the basic transaction logic.
-pub type SignedExtra = (
- system::CheckSpecVersion,
- system::CheckTxVersion,
- system::CheckGenesis,
- system::CheckEra,
- system::CheckNonce,
- system::CheckWeight,
- pallet_transaction_payment::ChargeTransactionPayment,
- pallet_grandpa::ValidateEquivocationReport,
-);
-
-/// Unchecked extrinsic type as expected by this runtime.
-pub type UncheckedExtrinsic = generic::UncheckedExtrinsic;
-/// Executive: handles dispatch to the various modules.
-pub type Executive =
- frame_executive::Executive, Runtime, AllModules>;
-
-impl_runtime_apis! {
- impl sp_api::Core for Runtime {
- fn version() -> RuntimeVersion {
- VERSION
- }
-
- fn execute_block(block: Block) {
- Executive::execute_block(block)
- }
-
- fn initialize_block(header: &::Header) {
- Executive::initialize_block(header)
- }
- }
-
- impl sp_api::Metadata for Runtime {
- fn metadata() -> OpaqueMetadata {
- Runtime::metadata().into()
- }
- }
-
- impl sp_block_builder::BlockBuilder for Runtime {
- fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult {
- Executive::apply_extrinsic(extrinsic)
- }
-
- fn finalize_block() -> ::Header {
- Executive::finalize_block()
- }
-
- fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> {
- data.create_extrinsics()
- }
-
- fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
- data.check_extrinsics(&block)
- }
-
- fn random_seed() -> ::Hash {
- RandomnessCollectiveFlip::random_seed()
- }
- }
-
- impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime {
- fn validate_transaction(
- source: TransactionSource,
- tx: ::Extrinsic,
- ) -> TransactionValidity {
- Executive::validate_transaction(source, tx)
- }
- }
-
- impl sp_offchain::OffchainWorkerApi for Runtime {
- fn offchain_worker(header: &::Header) {
- Executive::offchain_worker(header)
- }
- }
-
- impl fg_primitives::GrandpaApi for Runtime {
- fn grandpa_authorities() -> GrandpaAuthorityList {
- Grandpa::grandpa_authorities()
- }
-
- fn submit_report_equivocation_extrinsic(
- equivocation_proof: fg_primitives::EquivocationProof<
- ::Hash,
- NumberFor,
- >,
- key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
- ) -> Option<()> {
- let key_owner_proof = key_owner_proof.decode()?;
-
- Grandpa::submit_report_equivocation_extrinsic(
- equivocation_proof,
- key_owner_proof,
- )
- }
-
- fn generate_key_ownership_proof(
- _set_id: fg_primitives::SetId,
- authority_id: GrandpaId,
- ) -> Option {
- use codec::Encode;
-
- Historical::prove((fg_primitives::KEY_TYPE, authority_id))
- .map(|p| p.encode())
- .map(fg_primitives::OpaqueKeyOwnershipProof::new)
- }
- }
-
- impl sp_consensus_babe::BabeApi for Runtime {
- fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
- // The choice of `c` parameter (where `1 - c` represents the
- // probability of a slot being empty), is done in accordance to the
- // slot duration and expected target block time, for safely
- // resisting network delays of maximum two seconds.
- //
- sp_consensus_babe::BabeGenesisConfiguration {
- slot_duration: Babe::slot_duration(),
- epoch_length: EpochDuration::get(),
- c: PRIMARY_PROBABILITY,
- genesis_authorities: Babe::authorities(),
- randomness: Babe::randomness(),
- allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots,
- }
- }
-
- fn current_epoch_start() -> sp_consensus_babe::SlotNumber {
- Babe::current_epoch_start()
- }
- }
-
- impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime {
- fn authorities() -> Vec {
- AuthorityDiscovery::authorities()
- }
- }
-
- impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime {
- fn account_nonce(account: AccountId) -> Index {
- System::account_nonce(account)
- }
- }
-
- impl sp_session::SessionKeys for Runtime {
- fn generate_session_keys(seed: Option>) -> Vec {
- SessionKeys::generate(seed)
- }
- fn decode_session_keys(
- encoded: Vec,
- ) -> Option, KeyTypeId)>> {
- SessionKeys::decode_into_raw_public_keys(&encoded)
- }
- }
-
- impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
- Block,
- Balance,
- UncheckedExtrinsic,
- > for Runtime {
- fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo {
- TransactionPayment::query_info(uxt, len)
- }
- }
-}
diff --git a/runtime/src/migration.rs b/runtime/src/migration.rs
deleted file mode 100644
index 64e527b541..0000000000
--- a/runtime/src/migration.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Clippy linter warning
-#![allow(clippy::redundant_closure_call)] // disable it because of the substrate lib design
-
-use crate::VERSION;
-use frame_support::weights::Weight;
-use frame_support::{debug, decl_event, decl_module, decl_storage};
-
-impl Module {
- /// This method is called from on_initialize() when a runtime upgrade is detected. This
- /// happens when the runtime spec version is found to be higher than the stored value.
- /// Important to note this method should be carefully maintained, because it runs on every runtime
- /// upgrade.
- fn runtime_upgraded() {
- debug::print!("Running runtime upgraded handler");
-
- // Add initialization of modules introduced in new runtime release. Typically this
- // would be any new storage values that need an initial value which would not
- // have been initialized with config() or build() chainspec construction mechanism.
- // Other tasks like resetting values, migrating values etc.
- }
-}
-
-pub trait Trait:
- system::Trait
- + minting::Trait
- + proposals_codex::Trait
- + working_group::Trait
- + storage::data_directory::Trait
- + storage::data_object_storage_registry::Trait
-{
- type Event: From> + Into<::Event>;
-}
-
-decl_storage! {
- trait Store for Module as Migration {
- /// Records at what runtime spec version the store was initialized. At genesis this will be
- /// initialized to Some(VERSION.spec_version). It is an Option because the first time the module
- /// was introduced was as a runtime upgrade and type was never changed.
- /// When the runtime is upgraded the spec version be updated.
- pub SpecVersion get(fn spec_version) build(|_config: &GenesisConfig| {
- Some(VERSION.spec_version)
- }) : Option;
- }
-}
-
-decl_event! {
- pub enum Event where ::BlockNumber {
- Migrated(BlockNumber, u32),
- }
-}
-
-decl_module! {
- pub struct Module for enum Call where origin: T::Origin {
- fn deposit_event() = default;
-
- fn on_initialize(_now: T::BlockNumber) -> Weight {
- if Self::spec_version().map_or(true, |spec_version| VERSION.spec_version > spec_version) {
- // Mark store version with current version of the runtime
- SpecVersion::put(VERSION.spec_version);
-
- // Run migrations and store initializers
- Self::runtime_upgraded();
-
- Self::deposit_event(RawEvent::Migrated(
- >::block_number(),
- VERSION.spec_version,
- ));
- }
-
- 10_000_000 // TODO adjust weight
- }
- }
-}
-
-impl Module {}
diff --git a/runtime/src/primitives.rs b/runtime/src/primitives.rs
new file mode 100644
index 0000000000..99ea7258e3
--- /dev/null
+++ b/runtime/src/primitives.rs
@@ -0,0 +1,95 @@
+//! Low-level types used throughout the Substrate code.
+
+#![warn(missing_docs)]
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use sp_runtime::{
+ traits::{IdentifyAccount, Verify},
+ MultiSignature,
+};
+
+/// Priority for a transaction. Additive. Higher is better.
+pub type TransactionPriority = u64;
+
+/// Alias for ContentId, used in various places.
+pub type ContentId = sp_core::H256;
+
+/// An index to a block.
+pub type BlockNumber = u32;
+
+/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
+pub type Signature = MultiSignature;
+
+/// Some way of identifying an account on the chain. We intentionally make it equivalent
+/// to the public key of our transaction signing scheme.
+pub type AccountId = <::Signer as IdentifyAccount>::AccountId;
+
+/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
+/// never know...
+pub type AccountIndex = u32;
+
+/// Balance of an account.
+pub type Balance = u128;
+
+/// Index of a transaction in the chain.
+pub type Index = u32;
+
+/// A hash of some data used by the chain.
+pub type Hash = sp_core::H256;
+
+/// Moment type
+pub type Moment = u64;
+
+/// Credential type
+pub type Credential = u64;
+
+/// Represents a thread identifier for both Forum and Proposals Discussion
+///
+/// Note: Both modules expose type names ThreadId and PostId (which are defined on their Trait) and
+/// used in state storage and dispatchable method's argument types,
+/// and are therefore part of the public API/metadata of the runtime.
+/// In the current version the polkadot-js/api that is used and is compatible with the runtime,
+/// the type registry has flat namespace and its not possible
+/// to register identically named types from different modules, separately. And so we MUST configure
+/// the underlying types to be identicaly to avoid issues with encoding/decoding these types on the client side.
+pub type ThreadId = u64;
+
+/// Represents a post identifier for both Forum and Proposals Discussion
+///
+/// See the Note about ThreadId
+pub type PostId = u64;
+
+/// Represent an actor in membership group, which is the same in the working groups.
+pub type ActorId = u64;
+
+/// App-specific crypto used for reporting equivocation/misbehavior in BABE and
+/// GRANDPA. Any rewards for misbehavior reporting will be paid out to this
+/// account.
+pub mod report {
+ use super::{Signature, Verify};
+ use sp_core::crypto::{key_types, KeyTypeId};
+ use system::offchain::AppCrypto;
+
+ /// Key type for the reporting module. Used for reporting BABE and GRANDPA
+ /// equivocations.
+ pub const KEY_TYPE: KeyTypeId = key_types::REPORTING;
+
+ mod app {
+ use sp_application_crypto::{app_crypto, sr25519};
+ app_crypto!(sr25519, super::KEY_TYPE);
+ }
+
+ /// Identity of the equivocation/misbehavior reporter.
+ pub type ReporterId = app::Public;
+
+ /// An `AppCrypto` type to allow submitting signed transactions using the reporting
+ /// application key as signer.
+ pub struct ReporterAppCrypto;
+
+ impl AppCrypto<::Signer, Signature> for ReporterAppCrypto {
+ type RuntimeAppPublic = ReporterId;
+ type GenericSignature = sp_core::sr25519::Signature;
+ type GenericPublic = sp_core::sr25519::Public;
+ }
+}
diff --git a/runtime/src/runtime_api.rs b/runtime/src/runtime_api.rs
new file mode 100644
index 0000000000..8e4e7298df
--- /dev/null
+++ b/runtime/src/runtime_api.rs
@@ -0,0 +1,242 @@
+use frame_support::inherent::{CheckInherentsResult, InherentData};
+use frame_support::traits::{KeyOwnerProofSystem, Randomness};
+use frame_support::unsigned::{TransactionSource, TransactionValidity};
+use pallet_contracts_rpc_runtime_api::ContractExecResult;
+use pallet_grandpa::fg_primitives;
+use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
+use sp_api::impl_runtime_apis;
+use sp_core::crypto::KeyTypeId;
+use sp_core::OpaqueMetadata;
+use sp_runtime::traits::{BlakeTwo256, Block as BlockT, NumberFor};
+use sp_runtime::{generic, ApplyExtrinsicResult};
+use sp_std::vec::Vec;
+
+use crate::constants::PRIMARY_PROBABILITY;
+use crate::{
+ AccountId, AuthorityDiscoveryId, Balance, BlockNumber, EpochDuration, GrandpaAuthorityList,
+ GrandpaId, Hash, Index, RuntimeVersion, Signature, VERSION,
+};
+use crate::{
+ AllModules, AuthorityDiscovery, Babe, Call, Contracts, Grandpa, Historical, InherentDataExt,
+ RandomnessCollectiveFlip, Runtime, SessionKeys, System, TransactionPayment,
+};
+
+/// The SignedExtension to the basic transaction logic.
+pub type SignedExtra = (
+ system::CheckSpecVersion,
+ system::CheckTxVersion,
+ system::CheckGenesis,
+ system::CheckEra,
+ system::CheckNonce,
+ system::CheckWeight,
+ pallet_transaction_payment::ChargeTransactionPayment,
+ pallet_grandpa::ValidateEquivocationReport,
+);
+
+/// Digest item type.
+pub type DigestItem = generic::DigestItem;
+
+/// Block header type as expected by this runtime.
+pub type Header = generic::Header;
+
+/// Block type as expected by this runtime.
+pub type Block = generic::Block;
+
+/// A Block signed with a Justification
+pub type SignedBlock = generic::SignedBlock;
+
+/// BlockId type as expected by this runtime.
+pub type BlockId = generic::BlockId;
+
+/// Unchecked extrinsic type as expected by this runtime.
+pub type UncheckedExtrinsic = generic::UncheckedExtrinsic;
+
+/// Executive: handles dispatch to the various modules.
+pub type Executive =
+ frame_executive::Executive, Runtime, AllModules>;
+
+/// Export of the private const generated within the macro.
+pub const EXPORTED_RUNTIME_API_VERSIONS: sp_version::ApisVec = RUNTIME_API_VERSIONS;
+
+impl_runtime_apis! {
+ impl sp_api::Core for Runtime {
+ fn version() -> RuntimeVersion {
+ VERSION
+ }
+
+ fn execute_block(block: Block) {
+ Executive::execute_block(block)
+ }
+
+ fn initialize_block(header: &::Header) {
+ Executive::initialize_block(header)
+ }
+ }
+
+ impl sp_api::Metadata for Runtime {
+ fn metadata() -> OpaqueMetadata {
+ Runtime::metadata().into()
+ }
+ }
+
+ impl sp_block_builder::BlockBuilder for Runtime {
+ fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult {
+ Executive::apply_extrinsic(extrinsic)
+ }
+
+ fn finalize_block() -> ::Header {
+ Executive::finalize_block()
+ }
+
+ fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> {
+ data.create_extrinsics()
+ }
+
+ fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
+ data.check_extrinsics(&block)
+ }
+
+ fn random_seed() -> ::Hash {
+ RandomnessCollectiveFlip::random_seed()
+ }
+ }
+
+ impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime {
+ fn validate_transaction(
+ source: TransactionSource,
+ tx: ::Extrinsic,
+ ) -> TransactionValidity {
+ Executive::validate_transaction(source, tx)
+ }
+ }
+
+ impl sp_offchain::OffchainWorkerApi for Runtime {
+ fn offchain_worker(header: &::Header) {
+ Executive::offchain_worker(header)
+ }
+ }
+
+ impl fg_primitives::GrandpaApi for Runtime {
+ fn grandpa_authorities() -> GrandpaAuthorityList {
+ Grandpa::grandpa_authorities()
+ }
+
+ fn submit_report_equivocation_extrinsic(
+ equivocation_proof: fg_primitives::EquivocationProof<
+ ::Hash,
+ NumberFor,
+ >,
+ key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
+ ) -> Option<()> {
+ let key_owner_proof = key_owner_proof.decode()?;
+
+ Grandpa::submit_report_equivocation_extrinsic(
+ equivocation_proof,
+ key_owner_proof,
+ )
+ }
+
+ fn generate_key_ownership_proof(
+ _set_id: fg_primitives::SetId,
+ authority_id: GrandpaId,
+ ) -> Option {
+ use codec::Encode;
+
+ Historical::prove((fg_primitives::KEY_TYPE, authority_id))
+ .map(|p| p.encode())
+ .map(fg_primitives::OpaqueKeyOwnershipProof::new)
+ }
+ }
+
+ impl sp_consensus_babe::BabeApi for Runtime {
+ fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
+ // The choice of `c` parameter (where `1 - c` represents the
+ // probability of a slot being empty), is done in accordance to the
+ // slot duration and expected target block time, for safely
+ // resisting network delays of maximum two seconds.
+ //
+ sp_consensus_babe::BabeGenesisConfiguration {
+ slot_duration: Babe::slot_duration(),
+ epoch_length: EpochDuration::get(),
+ c: PRIMARY_PROBABILITY,
+ genesis_authorities: Babe::authorities(),
+ randomness: Babe::randomness(),
+ allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots,
+ }
+ }
+
+ fn current_epoch_start() -> sp_consensus_babe::SlotNumber {
+ Babe::current_epoch_start()
+ }
+ }
+
+ impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime {
+ fn authorities() -> Vec {
+ AuthorityDiscovery::authorities()
+ }
+ }
+
+ impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime {
+ fn account_nonce(account: AccountId) -> Index {
+ System::account_nonce(account)
+ }
+ }
+
+
+ impl pallet_contracts_rpc_runtime_api::ContractsApi
+ for Runtime
+ {
+ fn call(
+ origin: AccountId,
+ dest: AccountId,
+ value: Balance,
+ gas_limit: u64,
+ input_data: Vec