,
+ /// Transaction pool instance.
+ pub pool: Arc,
+ /// Remote access to the blockchain (async).
+ pub remote_blockchain: Arc>,
+ /// Fetcher instance.
+ pub fetcher: Arc,
+}
/// Full client dependencies.
pub struct FullDeps {
@@ -23,42 +41,137 @@ pub struct FullDeps {
pub pool: Arc,
/// Whether to deny unsafe calls
pub deny_unsafe: DenyUnsafe,
+ // /// The Node authority flag
+ pub is_authority: bool,
+ /// Whether to enable dev signer
+ pub enable_dev_signer: bool,
+ // /// Network service
+ pub network: Arc>,
+ /// Manual seal command sink
+ pub command_sink: Option>>,
}
-/// Instantiate all full RPC extensions.
-pub fn create_full(
+/// Instantiate all Full RPC extensions.
+pub fn create_full(
deps: FullDeps,
+ subscription_task_executor: SubscriptionTaskExecutor
) -> jsonrpc_core::IoHandler where
- C: ProvideRuntimeApi,
- C: HeaderBackend + HeaderMetadata + 'static,
+ BE: Backend + 'static,
+ BE::State: StateBackend,
+ C: ProvideRuntimeApi + StorageProvider + AuxStore,
+ C: BlockchainEvents,
+ C: HeaderBackend + HeaderMetadata,
C: Send + Sync + 'static,
C::Api: substrate_frame_rpc_system::AccountNonceApi,
- C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
C::Api: BlockBuilder,
- P: TransactionPool + 'static,
+ C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
+ C::Api: fp_rpc::EthereumRuntimeRPCApi,
+ ::Error: fmt::Debug,
+ P: TransactionPool + 'static,
{
use substrate_frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
+ use fc_rpc::{
+ EthApi, EthApiServer, NetApi, NetApiServer, EthPubSubApi, EthPubSubApiServer,
+ Web3Api, Web3ApiServer, EthDevSigner, EthSigner, HexEncodedIdProvider
+ };
let mut io = jsonrpc_core::IoHandler::default();
let FullDeps {
client,
pool,
deny_unsafe,
+ is_authority,
+ network,
+ command_sink,
+ enable_dev_signer,
} = deps;
io.extend_with(
- SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe))
+ SystemApi::to_delegate(FullSystem::new(client.clone(), pool.clone(), deny_unsafe))
);
-
io.extend_with(
TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))
);
- // Extend this RPC with a custom API by using the following syntax.
- // `YourRpcStruct` should have a reference to a client, which is needed
- // to call into the runtime.
- // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));`
+ let mut signers = Vec::new();
+ if enable_dev_signer {
+ signers.push(Box::new(EthDevSigner::new()) as Box);
+ }
+ io.extend_with(
+ EthApiServer::to_delegate(EthApi::new(
+ client.clone(),
+ pool.clone(),
+ mathchain_runtime::TransactionConverter,
+ network.clone(),
+ signers,
+ is_authority,
+ ))
+ );
+
+ io.extend_with(
+ NetApiServer::to_delegate(NetApi::new(
+ client.clone(),
+ network.clone(),
+ ))
+ );
+
+ io.extend_with(
+ Web3ApiServer::to_delegate(Web3Api::new(
+ client.clone(),
+ ))
+ );
+
+ io.extend_with(
+ EthPubSubApiServer::to_delegate(EthPubSubApi::new(
+ pool.clone(),
+ client.clone(),
+ network.clone(),
+ SubscriptionManager::::with_id_provider(
+ HexEncodedIdProvider::default(),
+ Arc::new(subscription_task_executor)
+ ),
+ ))
+ );
+
+ match command_sink {
+ Some(command_sink) => {
+ io.extend_with(
+ // We provide the rpc handler with the sending end of the channel to allow the rpc
+ // send EngineCommands to the background block authorship task.
+ ManualSealApi::to_delegate(ManualSeal::new(command_sink)),
+ );
+ }
+ _ => {}
+ }
+
+ 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 326dfd9..cd50f4d 100644
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -1,15 +1,20 @@
//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
-use std::sync::Arc;
-use std::time::Duration;
+use std::{sync::Arc, cell::RefCell, time::Duration};
use sc_client_api::{ExecutorProvider, RemoteBackend};
-use mathchain_runtime::{self, opaque::Block, RuntimeApi};
+use mathchain_consensus::MathchainBlockImport;
+use mathchain_runtime::{self, opaque::Block, RuntimeApi, SLOT_DURATION};
use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
-use sp_inherents::InherentDataProviders;
+use sc_consensus_manual_seal::{self as manual_seal};
+
+use sp_inherents::{InherentDataProviders, ProvideInherentData, InherentIdentifier, InherentData};
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState};
+use crate::cli::Sealing;
+// use sp_runtime::traits::{Block as BlockT};
+use sp_timestamp::InherentError;
// Our native executor instance.
native_executor_instance!(
@@ -23,6 +28,51 @@ type FullClient = sc_service::TFullClient;
type FullBackend = sc_service::TFullBackend;
type FullSelectChain = sc_consensus::LongestChain;
+pub enum ConsensusResult {
+ Aura(
+ sc_consensus_aura::AuraBlockImport<
+ Block,
+ FullClient,
+ MathchainBlockImport<
+ Block,
+ sc_finality_grandpa::GrandpaBlockImport,
+ FullClient
+ >,
+ AuraPair
+ >,
+ sc_finality_grandpa::LinkHalf
+ ),
+ ManualSeal(MathchainBlockImport, FullClient>, Sealing)
+}
+
+/// Provide a mock duration starting at 0 in millisecond for timestamp inherent.
+/// Each call will increment timestamp by slot_duration making Aura think time has passed.
+pub struct MockTimestampInherentDataProvider;
+
+pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";
+
+thread_local!(static TIMESTAMP: RefCell = RefCell::new(0));
+
+impl ProvideInherentData for MockTimestampInherentDataProvider {
+ fn inherent_identifier(&self) -> &'static InherentIdentifier {
+ &INHERENT_IDENTIFIER
+ }
+
+ fn provide_inherent_data(
+ &self,
+ inherent_data: &mut InherentData,
+ ) -> Result<(), sp_inherents::Error> {
+ TIMESTAMP.with(|x| {
+ *x.borrow_mut() += SLOT_DURATION;
+ inherent_data.put_data(INHERENT_IDENTIFIER, &*x.borrow())
+ })
+ }
+
+ fn error_to_string(&self, error: &[u8]) -> Option {
+ InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e))
+ }
+}
+
/// Can be called for a `Configuration` to check if it is a configuration for the `Crab` network.
pub trait IdentifyVariant {
/// Returns if this is a configuration for the `Crab` network.
@@ -42,23 +92,15 @@ impl IdentifyVariant for Box {
}
}
-pub fn new_partial(config: &Configuration) -> Result) -> Result,
+ sp_consensus::import_queue::BasicQueue>,
sc_transaction_pool::FullPool,
- (
- sc_consensus_aura::AuraBlockImport<
- Block,
- FullClient,
- sc_finality_grandpa::GrandpaBlockImport,
- AuraPair
- >,
- sc_finality_grandpa::LinkHalf
- )
->, ServiceError> {
+ ConsensusResult,
+ >, ServiceError> {
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
- let (client, backend, keystore, task_manager) =
+ let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::(&config)?;
let client = Arc::new(client);
@@ -71,12 +113,43 @@ pub fn new_partial(config: &Configuration) -> Result), select_chain.clone(),
)?;
+ let mathchain_block_import = MathchainBlockImport::new(
+ grandpa_block_import.clone(),
+ client.clone(),
+ true
+ );
+
let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
- grandpa_block_import.clone(), client.clone(),
+ mathchain_block_import, client.clone(),
);
let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
@@ -92,35 +165,54 @@ pub fn new_partial(config: &Configuration) -> Result Result {
+pub fn new_full(
+ config: Configuration,
+ sealing: Option,
+ enable_dev_signer: bool,
+) -> Result {
let sc_service::PartialComponents {
- client, backend, mut task_manager, import_queue, keystore, select_chain, transaction_pool,
- inherent_data_providers,
- other: (block_import, grandpa_link),
- } = new_partial(&config)?;
+ client, backend, mut task_manager, import_queue, keystore_container,
+ select_chain, transaction_pool, inherent_data_providers, other: consensus_result,
+ } = new_partial(&config, sealing)?;
+
+ let (network, network_status_sinks, system_rpc_tx, network_starter) = match consensus_result {
+ ConsensusResult::ManualSeal(_, _) => {
+ sc_service::build_network(sc_service::BuildNetworkParams {
+ config: &config,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ spawn_handle: task_manager.spawn_handle(),
+ import_queue,
+ on_demand: None,
+ block_announce_validator_builder: None,
+ finality_proof_request_builder: Some(Box::new(sc_network::config::DummyFinalityProofRequestBuilder)),
+ finality_proof_provider: None,
+ })?
+ },
+ ConsensusResult::Aura(_, _) => {
+ sc_service::build_network(sc_service::BuildNetworkParams {
+ config: &config,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ spawn_handle: task_manager.spawn_handle(),
+ import_queue,
+ on_demand: None,
+ block_announce_validator_builder: None,
+ finality_proof_request_builder: None,
+ finality_proof_provider: Some(GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone())),
+ })?
+ }
+ };
- let finality_proof_provider =
- GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
-
- let (network, network_status_sinks, system_rpc_tx, network_starter) =
- sc_service::build_network(sc_service::BuildNetworkParams {
- config: &config,
- client: client.clone(),
- transaction_pool: transaction_pool.clone(),
- spawn_handle: task_manager.spawn_handle(),
- import_queue,
- on_demand: None,
- block_announce_validator_builder: None,
- finality_proof_request_builder: None,
- finality_proof_provider: Some(finality_proof_provider.clone()),
- })?;
+ // Channel for the rpc handler to communicate with the authorship task.
+ let (command_sink, commands_stream) = futures::channel::mpsc::channel(1000);
if config.offchain_worker.enabled {
sc_service::build_offchain_workers(
@@ -134,26 +226,34 @@ pub fn new_full(config: Configuration) -> Result {
let enable_grandpa = !config.disable_grandpa;
let prometheus_registry = config.prometheus_registry().cloned();
let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default();
+ let is_authority = role.is_authority();
+ let subscription_task_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());
let rpc_extensions_builder = {
let client = client.clone();
let pool = transaction_pool.clone();
-
+ let network = network.clone();
Box::new(move |deny_unsafe, _| {
let deps = crate::rpc::FullDeps {
client: client.clone(),
pool: pool.clone(),
deny_unsafe,
+ is_authority,
+ enable_dev_signer,
+ network: network.clone(),
+ command_sink: Some(command_sink.clone())
};
-
- crate::rpc::create_full(deps)
+ crate::rpc::create_full(
+ deps,
+ subscription_task_executor.clone()
+ )
})
};
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
network: network.clone(),
client: client.clone(),
- keystore: keystore.clone(),
+ keystore: keystore_container.sync_keystore(),
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
telemetry_connection_sinks: telemetry_connection_sinks.clone(),
@@ -163,82 +263,128 @@ pub fn new_full(config: Configuration) -> Result {
backend, network_status_sinks, system_rpc_tx, config,
})?;
- if role.is_authority() {
- let proposer = sc_basic_authorship::ProposerFactory::new(
- client.clone(),
- transaction_pool,
- prometheus_registry.as_ref(),
- );
-
- let can_author_with =
- sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
-
- let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>(
- sc_consensus_aura::slot_duration(&*client)?,
- client.clone(),
- select_chain,
- block_import,
- proposer,
- network.clone(),
- inherent_data_providers.clone(),
- force_authoring,
- keystore.clone(),
- can_author_with,
- )?;
-
- // the AURA authoring task is considered essential, i.e. if it
- // fails we take down the service with it.
- task_manager.spawn_essential_handle().spawn_blocking("aura", aura);
- }
-
- // 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 role.is_authority() {
- Some(keystore as sp_core::traits::BareCryptoStorePtr)
- } else {
- None
- };
-
- let grandpa_config = sc_finality_grandpa::Config {
- // FIXME #1578 make this available through chainspec
- gossip_duration: Duration::from_millis(333),
- justification_period: 512,
- name: Some(name),
- observer_enabled: false,
- keystore,
- is_authority: role.is_network_authority(),
- };
-
- 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 = sc_finality_grandpa::GrandpaParams {
- config: grandpa_config,
- link: grandpa_link,
- network,
- inherent_data_providers,
- telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()),
- voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),
- prometheus_registry,
- shared_voter_state: SharedVoterState::empty(),
- };
-
- // the GRANDPA voter task is considered infallible, i.e.
- // if it fails we take down the service with it.
- task_manager.spawn_essential_handle().spawn_blocking(
- "grandpa-voter",
- sc_finality_grandpa::run_grandpa_voter(grandpa_config)?
- );
- } else {
- sc_finality_grandpa::setup_disabled_grandpa(
- client,
- &inherent_data_providers,
- network,
- )?;
+ match consensus_result {
+ ConsensusResult::ManualSeal(block_import, sealing) => {
+ if role.is_authority() {
+ let env = sc_basic_authorship::ProposerFactory::new(
+ task_manager.spawn_handle(),
+ client.clone(),
+ transaction_pool.clone(),
+ prometheus_registry.as_ref(),
+ );
+
+ // Background authorship future
+ match sealing {
+ Sealing::Manual => {
+ let authorship_future = manual_seal::run_manual_seal(
+ manual_seal::ManualSealParams {
+ block_import,
+ env,
+ client,
+ pool: transaction_pool.pool().clone(),
+ commands_stream,
+ select_chain,
+ consensus_data_provider: None,
+ inherent_data_providers,
+ }
+ );
+ // we spawn the future on a background thread managed by service.
+ task_manager.spawn_essential_handle().spawn_blocking("manual-seal", authorship_future);
+ },
+ Sealing::Instant => {
+ let authorship_future = manual_seal::run_instant_seal(
+ manual_seal::InstantSealParams {
+ block_import,
+ env,
+ client: client.clone(),
+ pool: transaction_pool.pool().clone(),
+ select_chain,
+ consensus_data_provider: None,
+ inherent_data_providers,
+ }
+ );
+ // we spawn the future on a background thread managed by service.
+ task_manager.spawn_essential_handle().spawn_blocking("instant-seal", authorship_future);
+ }
+ };
+
+ }
+ log::info!("Manual Seal Ready");
+ },
+ ConsensusResult::Aura(aura_block_import, grandpa_link) => {
+ if role.is_authority() {
+ let proposer = sc_basic_authorship::ProposerFactory::new(
+ task_manager.spawn_handle(),
+ client.clone(),
+ transaction_pool.clone(),
+ prometheus_registry.as_ref(),
+ );
+
+ let can_author_with =
+ sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
+ let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>(
+ sc_consensus_aura::slot_duration(&*client)?,
+ client.clone(),
+ select_chain,
+ aura_block_import,
+ proposer,
+ network.clone(),
+ inherent_data_providers.clone(),
+ force_authoring,
+ keystore_container.sync_keystore(),
+ can_author_with,
+ )?;
+
+ // the AURA authoring task is considered essential, i.e. if it
+ // fails we take down the service with it.
+ task_manager.spawn_essential_handle().spawn_blocking("aura", aura);
+
+ // 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 role.is_authority() {
+ Some(keystore_container.sync_keystore())
+ } else {
+ None
+ };
+
+ let grandpa_config = sc_finality_grandpa::Config {
+ // FIXME #1578 make this available through chainspec
+ gossip_duration: Duration::from_millis(333),
+ justification_period: 512,
+ name: Some(name),
+ observer_enabled: false,
+ keystore,
+ is_authority: role.is_network_authority(),
+ };
+
+ 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 = sc_finality_grandpa::GrandpaParams {
+ config: grandpa_config,
+ link: grandpa_link,
+ network,
+ telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()),
+ voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),
+ prometheus_registry,
+ shared_voter_state: SharedVoterState::empty(),
+ };
+
+ // the GRANDPA voter task is considered infallible, i.e.
+ // if it fails we take down the service with it.
+ task_manager.spawn_essential_handle().spawn_blocking(
+ "grandpa-voter",
+ sc_finality_grandpa::run_grandpa_voter(grandpa_config)?
+ );
+ } else {
+ sc_finality_grandpa::setup_disabled_grandpa(network)?;
+ }
+ }
+ }
}
network_starter.start_network();
@@ -247,7 +393,7 @@ pub fn new_full(config: Configuration) -> Result {
/// Builds a new service for a light client.
pub fn new_light(config: Configuration) -> Result {
- let (client, backend, keystore, mut task_manager, on_demand) =
+ let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::(&config)?;
let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(
@@ -262,6 +408,7 @@ pub fn new_light(config: Configuration) -> Result {
client.clone(), backend.clone(), &(client.clone() as Arc<_>),
Arc::new(on_demand.checker().clone()) as Arc<_>,
)?;
+
let finality_proof_import = grandpa_block_import.clone();
let finality_proof_request_builder =
finality_proof_import.create_finality_proof_request_builder();
@@ -278,8 +425,17 @@ pub fn new_light(config: Configuration) -> Result {
sp_consensus::NeverCanAuthor,
)?;
+ let light_deps = crate::rpc::LightDeps {
+ remote_blockchain: backend.remote_blockchain(),
+ fetcher: on_demand.clone(),
+ client: client.clone(),
+ pool: transaction_pool.clone(),
+ };
+
+ let rpc_extensions = crate::rpc::create_light(light_deps);
+
let finality_proof_provider =
- GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
+ Arc::new(GrandpaFinalityProofProvider::new(backend.clone(), client.clone() as Arc<_>));
let (network, network_status_sinks, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
@@ -305,18 +461,18 @@ pub fn new_light(config: Configuration) -> Result {
transaction_pool,
task_manager: &mut task_manager,
on_demand: Some(on_demand),
- rpc_extensions_builder: Box::new(|_, _| ()),
+ rpc_extensions_builder: Box::new(sc_service::NoopRpcExtensionBuilder(rpc_extensions)),
telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(),
config,
client,
- keystore,
+ keystore: keystore_container.sync_keystore(),
backend,
network,
network_status_sinks,
system_rpc_tx,
- })?;
+ })?;
- network_starter.start_network();
+ network_starter.start_network();
- Ok(task_manager)
-}
+ Ok(task_manager)
+}
\ No newline at end of file
diff --git a/pallets/template/Cargo.toml b/pallets/template/Cargo.toml
index 5369597..108dbc3 100644
--- a/pallets/template/Cargo.toml
+++ b/pallets/template/Cargo.toml
@@ -19,13 +19,13 @@ package = 'parity-scale-codec'
version = '1.3.4'
[dependencies]
-frame-support = { default-features = false, version = '2.0.0' }
-frame-system = { default-features = false, version = '2.0.0' }
+frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
[dev-dependencies]
-sp-core = { default-features = false, version = '2.0.0' }
-sp-io = { default-features = false, version = '2.0.0' }
-sp-runtime = { default-features = false, version = '2.0.0' }
+sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-io = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
[features]
default = ['std']
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 90bdef6..0dc7583 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -19,42 +19,47 @@ wasm-builder-runner = { package = 'substrate-wasm-builder-runner', version = '1.
default-features = false
features = ['derive']
package = 'parity-scale-codec'
-version = '1.3.4'
+version = '1.3.0'
[dependencies]
hex-literal = { optional = true, version = '0.3.1' }
serde = { features = ['derive'], optional = true, version = '1.0.101' }
# local dependencies
-pallet-template = { path = '../pallets/template', default-features = false, version = '0.0.1' }
+# pallet-template = { path = '../pallets/template', default-features = false, version = '0.0.1' }
# Substrate dependencies
-frame-benchmarking = { default-features = false, optional = true, version = '2.0.0' }
-frame-executive = { default-features = false, version = '2.0.0' }
-frame-support = { default-features = false, version = '2.0.0' }
-frame-system = { default-features = false, version = '2.0.0' }
-frame-system-benchmarking = { default-features = false, optional = true, version = '2.0.0' }
-frame-system-rpc-runtime-api = { default-features = false, version = '2.0.0' }
-pallet-aura = { default-features = false, version = '2.0.0' }
-pallet-balances = { default-features = false, version = '2.0.0' }
-pallet-grandpa = { default-features = false, version = '2.0.0' }
-pallet-randomness-collective-flip = { default-features = false, version = '2.0.0' }
-pallet-recovery = { default-features = false, version = '2.0.0' }
-pallet-sudo = { default-features = false, version = '2.0.0' }
-pallet-timestamp = { default-features = false, version = '2.0.0' }
-pallet-transaction-payment = { default-features = false, version = '2.0.0' }
-pallet-transaction-payment-rpc-runtime-api = { default-features = false, version = '2.0.0' }
-sp-api = { default-features = false, version = '2.0.0' }
-sp-block-builder = { default-features = false, version = '2.0.0' }
-sp-consensus-aura = { default-features = false, version = '0.8.0' }
-sp-core = { default-features = false, version = '2.0.0' }
-sp-inherents = { default-features = false, version = '2.0.0' }
-sp-offchain = { default-features = false, version = '2.0.0' }
-sp-runtime = { default-features = false, version = '2.0.0' }
-sp-session = { default-features = false, version = '2.0.0' }
-sp-std = { default-features = false, version = '2.0.0' }
-sp-transaction-pool = { default-features = false, version = '2.0.0' }
-sp-version = { default-features = false, version = '2.0.0' }
+frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-executive = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-system-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+frame-system-rpc-runtime-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-aura = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-ethereum = { default-features = false, path = "../vendor/frontier/frame/ethereum" }
+pallet-evm = { default-features = false, path = "../vendor/frontier/frame/evm" }
+pallet-grandpa = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-randomness-collective-flip = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-recovery = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-sudo = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-transaction-payment = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+pallet-transaction-payment-rpc-runtime-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-block-builder = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-consensus-aura = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-inherents = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-io = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-offchain = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-session = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-transaction-pool = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+sp-version = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
+
+fp-rpc = { default-features = false, path = "../vendor/frontier/primitives/rpc" }
[features]
default = ['std']
@@ -81,7 +86,7 @@ std = [
'pallet-randomness-collective-flip/std',
'pallet-recovery/std',
'pallet-sudo/std',
- 'pallet-template/std',
+ # 'pallet-template/std',
'pallet-timestamp/std',
'pallet-transaction-payment/std',
'pallet-transaction-payment-rpc-runtime-api/std',
@@ -90,6 +95,7 @@ std = [
'sp-consensus-aura/std',
'sp-core/std',
'sp-inherents/std',
+ "sp-io/std",
'sp-offchain/std',
'sp-runtime/std',
'sp-session/std',
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index 857af6a..785c821 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -1,13 +1,14 @@
#![cfg_attr(not(feature = "std"), no_std)]
// `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.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
-use sp_std::prelude::*;
-use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
+use sp_std::{prelude::*, marker::PhantomData};
+use codec::{Encode, Decode};
+use sp_core::{crypto::KeyTypeId, OpaqueMetadata, U256, H160, H256};
use sp_runtime::{
ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature,
transaction_validity::{TransactionValidity, TransactionSource},
@@ -22,6 +23,8 @@ use pallet_grandpa::fg_primitives;
use sp_version::RuntimeVersion;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
+use sp_core::crypto::Public;
+
// A few exports that help ease life for downstream crates.
#[cfg(any(feature = "std", test))]
@@ -33,18 +36,24 @@ pub use pallet_recovery::Call as RecoveryCall;
pub use frame_support::{
construct_runtime, parameter_types, StorageValue,
- traits::{KeyOwnerProofSystem, Randomness},
+ traits::{KeyOwnerProofSystem, Randomness, FindAuthor},
weights::{
Weight, IdentityFee,
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
},
+ ConsensusEngineId,
+};
+use pallet_evm::{
+ Account as EVMAccount, FeeCalculator, HashedAddressMapping,
+ EnsureAddressTruncated, Runner,
};
+use fp_rpc::{TransactionStatus};
pub mod constants;
use constants::{currency::*};
/// Import the template pallet.
-pub use pallet_template;
+// pub use pallet_template;
/// An index to a block.
pub type BlockNumber = u32;
@@ -100,7 +109,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("mathchain"),
impl_name: create_runtime_str!("mathchain"),
authoring_version: 1,
- spec_version: 2,
+ spec_version: 3,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
@@ -282,9 +291,60 @@ impl pallet_sudo::Trait for Runtime {
type Call = Call;
}
-/// Configure the pallet template in pallets/template.
-impl pallet_template::Trait for Runtime {
+// /// Configure the pallet template in pallets/template.
+// impl pallet_template::Trait for Runtime {
+// type Event = Event;
+// }
+
+/// Fixed gas price of `1`.
+pub struct FixedGasPrice;
+
+impl FeeCalculator for FixedGasPrice {
+ fn min_gas_price() -> U256 {
+ // Gas price is always one token per gas.
+ 1.into()
+ }
+}
+
+parameter_types! {
+ pub const ChainId: u64 = 1140;
+}
+
+impl pallet_evm::Trait for Runtime {
+ type FeeCalculator = FixedGasPrice;
+ type GasToWeight = ();
+ type CallOrigin = EnsureAddressTruncated;
+ type WithdrawOrigin = EnsureAddressTruncated;
+ type AddressMapping = HashedAddressMapping;
+ type Currency = Balances;
type Event = Event;
+ type Runner = pallet_evm::runner::stack::Runner;
+ type Precompiles = (
+ pallet_evm::precompiles::ECRecover,
+ pallet_evm::precompiles::Sha256,
+ pallet_evm::precompiles::Ripemd160,
+ pallet_evm::precompiles::Identity,
+ );
+ type ChainId = ChainId;
+}
+
+pub struct EthereumFindAuthor(PhantomData);
+impl> FindAuthor for EthereumFindAuthor
+{
+ fn find_author<'a, I>(digests: I) -> Option where
+ I: 'a + IntoIterator-
+ {
+ if let Some(author_index) = F::find_author(digests) {
+ let authority_id = Aura::authorities()[author_index as usize].clone();
+ return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
+ }
+ None
+ }
+}
+
+impl pallet_ethereum::Trait for Runtime {
+ type Event = Event;
+ type FindAuthor = EthereumFindAuthor;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
@@ -304,10 +364,28 @@ construct_runtime!(
Sudo: pallet_sudo::{Module, Call, Config, Storage, Event},
Recovery: pallet_recovery::{Module, Call, Storage, Event},
// Include the custom logic from the template pallet in the runtime.
- TemplateModule: pallet_template::{Module, Call, Storage, Event},
+ // TemplateModule: pallet_template::{Module, Call, Storage, Event},
+ Ethereum: pallet_ethereum::{Module, Call, Storage, Event, Config, ValidateUnsigned},
+ EVM: pallet_evm::{Module, Config, Call, Storage, Event},
}
);
+pub struct TransactionConverter;
+
+impl fp_rpc::ConvertTransaction for TransactionConverter {
+ fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
+ UncheckedExtrinsic::new_unsigned(pallet_ethereum::Call::::transact(transaction).into())
+ }
+}
+
+impl fp_rpc::ConvertTransaction for TransactionConverter {
+ fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> opaque::UncheckedExtrinsic {
+ let extrinsic = UncheckedExtrinsic::new_unsigned(pallet_ethereum::Call::::transact(transaction).into());
+ let encoded = extrinsic.encode();
+ opaque::UncheckedExtrinsic::decode(&mut &encoded[..]).expect("Encoded extrinsic is always valid")
+ }
+}
+
/// The address format for describing accounts.
pub type Address = AccountId;
/// Block header type as expected by this runtime.
@@ -423,7 +501,6 @@ impl_runtime_apis! {
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
-
impl fg_primitives::GrandpaApi for Runtime {
fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities()
@@ -464,4 +541,95 @@ impl_runtime_apis! {
TransactionPayment::query_info(uxt, len)
}
}
+
+ impl fp_rpc::EthereumRuntimeRPCApi for Runtime {
+ fn chain_id() -> u64 {
+ ::ChainId::get()
+ }
+
+ fn account_basic(address: H160) -> EVMAccount {
+ EVM::account_basic(&address)
+ }
+
+ fn gas_price() -> U256 {
+ ::FeeCalculator::min_gas_price()
+ }
+
+ fn account_code_at(address: H160) -> Vec {
+ EVM::account_codes(address)
+ }
+
+ fn author() -> H160 {
+ >::find_author()
+ }
+
+ fn storage_at(address: H160, index: U256) -> H256 {
+ let mut tmp = [0u8; 32];
+ index.to_big_endian(&mut tmp);
+ EVM::account_storages(address, H256::from_slice(&tmp[..]))
+ }
+
+ fn call(
+ from: H160,
+ to: H160,
+ data: Vec,
+ value: U256,
+ gas_limit: U256,
+ gas_price: Option,
+ nonce: Option,
+ ) -> Result {
+ ::Runner::call(
+ from,
+ to,
+ data,
+ value,
+ gas_limit.low_u32(),
+ gas_price,
+ nonce,
+ ).map_err(|err| err.into())
+ }
+
+ fn create(
+ from: H160,
+ data: Vec,
+ value: U256,
+ gas_limit: U256,
+ gas_price: Option,
+ nonce: Option,
+ ) -> Result {
+ ::Runner::create(
+ from,
+ data,
+ value,
+ gas_limit.low_u32(),
+ gas_price,
+ nonce,
+ ).map_err(|err| err.into())
+ }
+
+ fn current_transaction_statuses() -> Option> {
+ Ethereum::current_transaction_statuses()
+ }
+
+ fn current_block() -> Option {
+ Ethereum::current_block()
+ }
+
+ fn current_receipts() -> Option> {
+ Ethereum::current_receipts()
+ }
+
+ fn current_all() -> (
+ Option,
+ Option>,
+ Option>
+ ) {
+ (
+ Ethereum::current_block(),
+ Ethereum::current_receipts(),
+ Ethereum::current_transaction_statuses()
+ )
+ }
+ }
+
}
diff --git a/vendor/frontier b/vendor/frontier
new file mode 160000
index 0000000..d438171
--- /dev/null
+++ b/vendor/frontier
@@ -0,0 +1 @@
+Subproject commit d43817123f773854405b3c14bb037b026215f1e3