From 95ed3220cabbde23c7643d4760c36321d3023825 Mon Sep 17 00:00:00 2001 From: "zongxiong.chen" Date: Mon, 23 Nov 2020 19:13:10 +0100 Subject: [PATCH 1/2] Format code style --- .rustfmt.toml | 18 + node/build.rs | 4 +- node/src/chain_spec.rs | 247 ++++----- node/src/cli.rs | 44 +- node/src/command.rs | 224 ++++---- node/src/lib.rs | 2 +- node/src/main.rs | 2 +- node/src/rpc.rs | 76 +-- node/src/service.rs | 599 +++++++++++---------- pallets/account-linker/src/lib.rs | 143 ++--- pallets/account-linker/src/mock.rs | 75 +-- pallets/account-linker/src/tests.rs | 4 +- pallets/account-linker/src/util.rs | 13 +- pallets/offchain-worker/src/lib.rs | 711 ++++++++++++------------ pallets/offchain-worker/src/tests.rs | 227 ++++---- runtime/build.rs | 12 +- runtime/src/lib.rs | 778 ++++++++++++++------------- 17 files changed, 1649 insertions(+), 1530 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..2555962 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,18 @@ +max_width = 100 +binop_separator = "Front" +blank_lines_upper_bound = 1 +brace_style = "SameLineWhere" +control_brace_style = "AlwaysSameLine" +comment_width = 100 +format_code_in_doc_comments = true +ignore = ['target'] +imports_indent = "Block" +indent_style = "Block" +merge_imports = true +merge_derives = true +newline_style = "Auto" +space_after_colon = true +space_before_colon = false +trailing_comma = "Vertical" +wrap_comments = true +hard_tabs = false diff --git a/node/build.rs b/node/build.rs index e3bfe31..f9d839f 100644 --- a/node/build.rs +++ b/node/build.rs @@ -1,7 +1,7 @@ use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; fn main() { - generate_cargo_keys(); + generate_cargo_keys(); - rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 16813f9..f1755a2 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,12 +1,12 @@ -use sp_core::{Pair, Public, sr25519}; use litentry_runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, - SudoConfig, SystemConfig, WASM_BINARY, Signature + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, + SystemConfig, WASM_BINARY, }; +use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; -use sp_runtime::traits::{Verify, IdentifyAccount}; -use sc_service::ChainType; +use sp_runtime::traits::{IdentifyAccount, Verify}; // The URL for the telemetry server. // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -16,142 +16,149 @@ pub type ChainSpec = sc_service::GenericChainSpec; /// Generate a crypto pair from seed. pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() } type AccountPublic = ::Signer; /// Generate an account ID from seed. -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, { - AccountPublic::from(get_from_seed::(seed)).into_account() + AccountPublic::from(get_from_seed::(seed)).into_account() } /// Generate an Aura authority key. pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - ( - get_from_seed::(s), - get_from_seed::(s), - ) + (get_from_seed::(s), get_from_seed::(s)) } pub fn development_config() -> Result { - let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; + let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; - Ok(ChainSpec::from_genesis( - // Name - "Development", - // ID - "dev", - ChainType::Development, - move || testnet_genesis( - wasm_binary, - // Initial PoA authorities - vec![ - authority_keys_from_seed("Alice"), - ], - // Sudo account - get_account_id_from_seed::("Alice"), - // Pre-funded accounts - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - ], - true, - ), - // Bootnodes - vec![], - // Telemetry - None, - // Protocol ID - None, - // Properties - None, - // Extensions - None, - )) + Ok(ChainSpec::from_genesis( + // Name + "Development", + // ID + "dev", + ChainType::Development, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![authority_keys_from_seed("Alice")], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + // Properties + None, + // Extensions + None, + )) } pub fn local_testnet_config() -> Result { - let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; + let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; - Ok(ChainSpec::from_genesis( - // Name - "Local Testnet", - // ID - "local_testnet", - ChainType::Local, - move || testnet_genesis( - wasm_binary, - // Initial PoA authorities - vec![ - authority_keys_from_seed("Alice"), - authority_keys_from_seed("Bob"), - ], - // Sudo account - get_account_id_from_seed::("Alice"), - // Pre-funded accounts - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - ], - true, - ), - // Bootnodes - vec![], - // Telemetry - None, - // Protocol ID - None, - // Properties - None, - // Extensions - None, - )) + Ok(ChainSpec::from_genesis( + // Name + "Local Testnet", + // ID + "local_testnet", + ChainType::Local, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![ + authority_keys_from_seed("Alice"), + authority_keys_from_seed("Bob"), + ], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + // Properties + None, + // Extensions + None, + )) } /// Configure initial storage state for FRAME modules. fn testnet_genesis( - wasm_binary: &[u8], - initial_authorities: Vec<(AuraId, GrandpaId)>, - root_key: AccountId, - endowed_accounts: Vec, - _enable_println: bool, + wasm_binary: &[u8], + initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool, ) -> GenesisConfig { - GenesisConfig { - frame_system: Some(SystemConfig { - // Add Wasm runtime to storage. - code: wasm_binary.to_vec(), - changes_trie_config: Default::default(), - }), - pallet_balances: Some(BalancesConfig { - // Configure endowed accounts with initial balance of 1 << 60. - balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), - }), - pallet_aura: Some(AuraConfig { - authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), - }), - pallet_grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), - }), - pallet_sudo: Some(SudoConfig { - // Assign network admin rights. - key: root_key, - }), - } + GenesisConfig { + frame_system: Some(SystemConfig { + // Add Wasm runtime to storage. + code: wasm_binary.to_vec(), + changes_trie_config: Default::default(), + }), + pallet_balances: Some(BalancesConfig { + // Configure endowed accounts with initial balance of 1 << 60. + balances: endowed_accounts + .iter() + .cloned() + .map(|k| (k, 1 << 60)) + .collect(), + }), + pallet_aura: Some(AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }), + pallet_grandpa: Some(GrandpaConfig { + authorities: initial_authorities + .iter() + .map(|x| (x.1.clone(), 1)) + .collect(), + }), + pallet_sudo: Some(SudoConfig { + // Assign network admin rights. + key: root_key, + }), + } } diff --git a/node/src/cli.rs b/node/src/cli.rs index f2faf17..639156f 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -1,39 +1,39 @@ -use structopt::StructOpt; use sc_cli::RunCmd; +use structopt::StructOpt; #[derive(Debug, StructOpt)] pub struct Cli { - #[structopt(subcommand)] - pub subcommand: Option, + #[structopt(subcommand)] + pub subcommand: Option, - #[structopt(flatten)] - pub run: RunCmd, + #[structopt(flatten)] + pub run: RunCmd, } #[derive(Debug, StructOpt)] pub enum Subcommand { - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), - /// Validate blocks. - CheckBlock(sc_cli::CheckBlockCmd), + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), - /// Export blocks. - ExportBlocks(sc_cli::ExportBlocksCmd), + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), - /// Export the state of a given block into a chain spec. - ExportState(sc_cli::ExportStateCmd), + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), - /// Import blocks. - ImportBlocks(sc_cli::ImportBlocksCmd), + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), - /// Remove the whole chain. - PurgeChain(sc_cli::PurgeChainCmd), + /// Remove the whole chain. + PurgeChain(sc_cli::PurgeChainCmd), - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), - /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] - Benchmark(frame_benchmarking_cli::BenchmarkCmd), + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/node/src/command.rs b/node/src/command.rs index 281f887..ea2d0aa 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -15,121 +15,143 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{chain_spec, service}; -use crate::cli::{Cli, Subcommand}; -use sc_cli::{SubstrateCli, RuntimeVersion, Role, ChainSpec}; -use sc_service::PartialComponents; +use crate::{ + chain_spec, + cli::{Cli, Subcommand}, + service, +}; use litentry_runtime::Block; +use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_service::PartialComponents; impl SubstrateCli for Cli { - fn impl_name() -> String { - "Substrate Node".into() - } + fn impl_name() -> String { + "Substrate Node".into() + } - fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() - } + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } - fn description() -> String { - env!("CARGO_PKG_DESCRIPTION").into() - } + fn description() -> String { + env!("CARGO_PKG_DESCRIPTION").into() + } - fn author() -> String { - env!("CARGO_PKG_AUTHORS").into() - } + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } - fn support_url() -> String { - "support.anonymous.an".into() - } + fn support_url() -> String { + "support.anonymous.an".into() + } - fn copyright_start_year() -> i32 { - 2017 - } + fn copyright_start_year() -> i32 { + 2017 + } - fn load_spec(&self, id: &str) -> Result, String> { - Ok(match id { - "dev" => Box::new(chain_spec::development_config()?), - "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => Box::new(chain_spec::ChainSpec::from_json_file( - std::path::PathBuf::from(path), - )?), - }) - } + fn load_spec(&self, id: &str) -> Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()?), + "" | "local" => Box::new(chain_spec::local_testnet_config()?), + path => Box::new(chain_spec::ChainSpec::from_json_file( + std::path::PathBuf::from(path), + )?), + }) + } - fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - &litentry_runtime::VERSION - } + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &litentry_runtime::VERSION + } } /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { - let cli = Cli::from_args(); + let cli = Cli::from_args(); - match &cli.subcommand { - Some(Subcommand::BuildSpec(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, - Some(Subcommand::CheckBlock(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, ..} - = service::new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::ExportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, ..} - = service::new_partial(&config)?; - Ok((cmd.run(client, config.database), task_manager)) - }) - }, - Some(Subcommand::ExportState(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, ..} - = service::new_partial(&config)?; - Ok((cmd.run(client, config.chain_spec), task_manager)) - }) - }, - Some(Subcommand::ImportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, ..} - = service::new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::PurgeChain(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) - }, - Some(Subcommand::Revert(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, ..} - = service::new_partial(&config)?; - Ok((cmd.run(client, backend), task_manager)) - }) - }, - Some(Subcommand::Benchmark(cmd)) => { - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; + match &cli.subcommand { + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + } + Some(Subcommand::CheckBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::ExportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, config.database), task_manager)) + }) + } + Some(Subcommand::ExportState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, config.chain_spec), task_manager)) + }) + } + Some(Subcommand::ImportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.database)) + } + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + backend, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, backend), task_manager)) + }) + } + Some(Subcommand::Benchmark(cmd)) => { + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) - } else { - Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`.".into()) - } - }, - None => { - let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - }) - } - } + runner.sync_run(|config| cmd.run::(config)) + } else { + Err("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into()) + } + } + None => { + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + }) + } + } } diff --git a/node/src/lib.rs b/node/src/lib.rs index 777c4f0..f117b8a 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -1,3 +1,3 @@ pub mod chain_spec; -pub mod service; pub mod rpc; +pub mod service; diff --git a/node/src/main.rs b/node/src/main.rs index 4449d28..a4182cd 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -9,5 +9,5 @@ mod command; mod rpc; fn main() -> sc_cli::Result<()> { - command::run() + command::run() } diff --git a/node/src/rpc.rs b/node/src/rpc.rs index c14266f..7a81075 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -8,57 +8,57 @@ use std::sync::Arc; use litentry_runtime::{opaque::Block, AccountId, Balance, Index}; +pub use sc_rpc_api::DenyUnsafe; use sp_api::ProvideRuntimeApi; -use sp_blockchain::{Error as BlockChainError, HeaderMetadata, HeaderBackend}; use sp_block_builder::BlockBuilder; -pub use sc_rpc_api::DenyUnsafe; +use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_transaction_pool::TransactionPool; - /// Full client dependencies. pub struct FullDeps { - /// The client instance to use. - pub client: Arc, - /// Transaction pool instance. - pub pool: Arc

, - /// Whether to deny unsafe calls - pub deny_unsafe: DenyUnsafe, + /// The client instance to use. + pub client: Arc, + /// Transaction pool instance. + pub pool: Arc

, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, } /// 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_transaction_payment_rpc::TransactionPaymentRuntimeApi, - C::Api: BlockBuilder, - P: TransactionPool + 'static, +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_transaction_payment_rpc::TransactionPaymentRuntimeApi, + C::Api: BlockBuilder, + P: TransactionPool + 'static, { - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + 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, - deny_unsafe, - } = deps; + let mut io = jsonrpc_core::IoHandler::default(); + let FullDeps { + client, + pool, + deny_unsafe, + } = deps; - io.extend_with( - SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)) - ); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + client.clone(), + pool, + deny_unsafe, + ))); - io.extend_with( - TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone())) - ); + 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, ...)));` + // 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, ...)));` - io + io } diff --git a/node/src/service.rs b/node/src/service.rs index f75265b..eeeb9f2 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -1,303 +1,342 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use std::sync::Arc; -use std::time::Duration; -use sc_client_api::{ExecutorProvider, RemoteBackend}; use litentry_runtime::{self, opaque::Block, RuntimeApi}; -use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; -use sp_inherents::InherentDataProviders; +use sc_client_api::{ExecutorProvider, RemoteBackend}; 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 sc_finality_grandpa::{ + FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState, +}; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_inherents::InherentDataProviders; +use std::{sync::Arc, time::Duration}; // Our native executor instance. native_executor_instance!( - pub Executor, - litentry_runtime::api::dispatch, - litentry_runtime::native_version, - frame_benchmarking::benchmarking::HostFunctions, + pub Executor, + litentry_runtime::api::dispatch, + litentry_runtime::native_version, + frame_benchmarking::benchmarking::HostFunctions, ); type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; -pub fn new_partial(config: &Configuration) -> Result, - sc_transaction_pool::FullPool, - ( - sc_consensus_aura::AuraBlockImport< - Block, - FullClient, - sc_finality_grandpa::GrandpaBlockImport, - AuraPair - >, - sc_finality_grandpa::LinkHalf - ) ->, ServiceError> { - let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - - let (client, backend, keystore, task_manager) = - sc_service::new_full_parts::(&config)?; - let client = Arc::new(client); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_handle(), - client.clone(), - ); - - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( - client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), - )?; - - let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( - grandpa_block_import.clone(), client.clone(), - ); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import.clone(), - Some(Box::new(grandpa_block_import.clone())), - None, - client.clone(), - inherent_data_providers.clone(), - &task_manager.spawn_handle(), - config.prometheus_registry(), - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - )?; - - Ok(sc_service::PartialComponents { - client, backend, task_manager, import_queue, keystore, select_chain, transaction_pool, - inherent_data_providers, - other: (aura_block_import, grandpa_link), - }) +pub fn new_partial( + config: &Configuration, +) -> Result< + sc_service::PartialComponents< + FullClient, + FullBackend, + FullSelectChain, + sp_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_consensus_aura::AuraBlockImport< + Block, + FullClient, + sc_finality_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, + AuraPair, + >, + sc_finality_grandpa::LinkHalf, + ), + >, + ServiceError, +> { + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let (client, backend, keystore, task_manager) = + sc_service::new_full_parts::(&config)?; + let client = Arc::new(client); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + )?; + + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), + client.clone(), + ); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import.clone(), + Some(Box::new(grandpa_block_import.clone())), + None, + client.clone(), + inherent_data_providers.clone(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + )?; + + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore, + select_chain, + transaction_pool, + inherent_data_providers, + other: (aura_block_import, grandpa_link), + }) } /// Builds a new service for a full client. pub fn new_full(config: Configuration) -> 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)?; - - 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()), - })?; - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(), - ); - } - - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let name = config.network.node_name.clone(); - let enable_grandpa = !config.disable_grandpa; - let prometheus_registry = config.prometheus_registry().cloned(); - let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); - - let rpc_extensions_builder = { - let client = client.clone(); - let pool = transaction_pool.clone(); - - Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - deny_unsafe, - }; - - crate::rpc::create_full(deps) - }) - }; - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), - client: client.clone(), - keystore: keystore.clone(), - task_manager: &mut task_manager, - transaction_pool: transaction_pool.clone(), - telemetry_connection_sinks: telemetry_connection_sinks.clone(), - rpc_extensions_builder: rpc_extensions_builder, - on_demand: None, - remote_blockchain: None, - 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, - )?; - } - - network_starter.start_network(); - Ok(task_manager) + 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)?; + + 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()), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); + + let rpc_extensions_builder = { + let client = client.clone(); + let pool = transaction_pool.clone(); + + Box::new(move |deny_unsafe, _| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + deny_unsafe, + }; + + crate::rpc::create_full(deps) + }) + }; + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore.clone(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + telemetry_connection_sinks: telemetry_connection_sinks.clone(), + rpc_extensions_builder: rpc_extensions_builder, + on_demand: None, + remote_blockchain: None, + 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)?; + } + + network_starter.start_network(); + Ok(task_manager) } /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore, mut task_manager, on_demand) = - sc_service::new_light_parts::(&config)?; - - let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_handle(), - client.clone(), - on_demand.clone(), - )); - - let grandpa_block_import = sc_finality_grandpa::light_block_import( - 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(); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), - client.clone(), - InherentDataProviders::new(), - &task_manager.spawn_handle(), - config.prometheus_registry(), - sp_consensus::NeverCanAuthor, - )?; - - 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: Some(on_demand.clone()), - block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), - })?; - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(), - ); - } - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - remote_blockchain: Some(backend.remote_blockchain()), - transaction_pool, - task_manager: &mut task_manager, - on_demand: Some(on_demand), - rpc_extensions_builder: Box::new(|_, _| ()), - telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), - config, - client, - keystore, - backend, - network, - network_status_sinks, - system_rpc_tx, - })?; - - network_starter.start_network(); - - Ok(task_manager) + let (client, backend, keystore, mut task_manager, on_demand) = + sc_service::new_light_parts::(&config)?; + + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( + config.transaction_pool.clone(), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + on_demand.clone(), + )); + + let grandpa_block_import = sc_finality_grandpa::light_block_import( + 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(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client.clone(), + InherentDataProviders::new(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + sp_consensus::NeverCanAuthor, + )?; + + 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: Some(on_demand.clone()), + block_announce_validator_builder: None, + finality_proof_request_builder: Some(finality_proof_request_builder), + finality_proof_provider: Some(finality_proof_provider), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + remote_blockchain: Some(backend.remote_blockchain()), + transaction_pool, + task_manager: &mut task_manager, + on_demand: Some(on_demand), + rpc_extensions_builder: Box::new(|_, _| ()), + telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), + config, + client, + keystore, + backend, + network, + network_status_sinks, + system_rpc_tx, + })?; + + network_starter.start_network(); + + Ok(task_manager) } diff --git a/pallets/account-linker/src/lib.rs b/pallets/account-linker/src/lib.rs index 370ab01..d8879ae 100644 --- a/pallets/account-linker/src/lib.rs +++ b/pallets/account-linker/src/lib.rs @@ -1,8 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::prelude::*; -use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch}; +use frame_support::{decl_error, decl_event, decl_module, decl_storage, dispatch}; use frame_system::ensure_signed; +use sp_std::prelude::*; #[cfg(test)] mod mock; @@ -13,84 +13,87 @@ mod tests; mod util; pub trait Trait: frame_system::Trait { - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; } decl_storage! { - trait Store for Module as TemplateModule { - pub EthereumLink get(fn eth_addresses): map hasher(blake2_128_concat) T::AccountId => Vec<[u8; 20]>; - } + trait Store for Module as TemplateModule { + pub EthereumLink get(fn eth_addresses): map hasher(blake2_128_concat) T::AccountId => Vec<[u8; 20]>; + } } decl_event!( - pub enum Event where AccountId = ::AccountId { - SomethingStored(u32, AccountId), - } + pub enum Event + where + AccountId = ::AccountId, + { + SomethingStored(u32, AccountId), + } ); decl_error! { - pub enum Error for Module { - EcdsaRecoverFailure, - } + pub enum Error for Module { + EcdsaRecoverFailure, + } } decl_module! { - pub struct Module for enum Call where origin: T::Origin { - // Errors must be initialized if they are used by the pallet. - type Error = Error; - - // Events must be initialized if they are used by the pallet. - fn deposit_event() = default; - - /// separate sig to r, s, v because runtime only support array parameter with length <= 32 - #[weight = 1] - pub fn link( - origin, - account: T::AccountId, - index: u32, - block_number: u32, - timestamp: u32, - r: [u8; 32], - s: [u8; 32], - v: u8, - ) -> dispatch::DispatchResult { - - let _ = ensure_signed(origin)?; - - let b1 = block_number.to_be_bytes(); - let b2 = timestamp.to_be_bytes(); - let bytes = [b1, b2].concat(); - - // TODO: add check, add accountId, add prefix - - let hash = sp_io::hashing::keccak_256(&bytes); - - let mut msg = [0u8; 32]; - let mut sig = [0u8; 65]; - - msg[..32].copy_from_slice(&hash[..32]); - sig[..32].copy_from_slice(&r[..32]); - sig[32..64].copy_from_slice(&s[..32]); - sig[64] = v; - - let addr = util::addr_from_sig(msg, sig) - .map_err(|_| Error::::EcdsaRecoverFailure)?; - - let index = index as usize; - let mut addrs = Self::eth_addresses(&account); - if (index >= addrs.len()) && (addrs.len() != 3) { // allow linking 3 eth addresses. TODO: do not use hard code - addrs.push(addr); - } else if (index >= addrs.len()) && (addrs.len() == 3) { - addrs[2] = addr; - } else { - addrs[index] = addr; - } - - >::insert(account, addrs); - - Ok(()) - - } - - } + pub struct Module for enum Call where origin: T::Origin { + // Errors must be initialized if they are used by the pallet. + type Error = Error; + + // Events must be initialized if they are used by the pallet. + fn deposit_event() = default; + + /// separate sig to r, s, v because runtime only support array parameter with length <= 32 + #[weight = 1] + pub fn link( + origin, + account: T::AccountId, + index: u32, + block_number: u32, + timestamp: u32, + r: [u8; 32], + s: [u8; 32], + v: u8, + ) -> dispatch::DispatchResult { + + let _ = ensure_signed(origin)?; + + let b1 = block_number.to_be_bytes(); + let b2 = timestamp.to_be_bytes(); + let bytes = [b1, b2].concat(); + + // TODO: add check, add accountId, add prefix + + let hash = sp_io::hashing::keccak_256(&bytes); + + let mut msg = [0u8; 32]; + let mut sig = [0u8; 65]; + + msg[..32].copy_from_slice(&hash[..32]); + sig[..32].copy_from_slice(&r[..32]); + sig[32..64].copy_from_slice(&s[..32]); + sig[64] = v; + + let addr = util::addr_from_sig(msg, sig) + .map_err(|_| Error::::EcdsaRecoverFailure)?; + + let index = index as usize; + let mut addrs = Self::eth_addresses(&account); + if (index >= addrs.len()) && (addrs.len() != 3) { // allow linking 3 eth addresses. TODO: do not use hard code + addrs.push(addr); + } else if (index >= addrs.len()) && (addrs.len() == 3) { + addrs[2] = addr; + } else { + addrs[index] = addr; + } + + >::insert(account, addrs); + + Ok(()) + + } + + } } diff --git a/pallets/account-linker/src/mock.rs b/pallets/account-linker/src/mock.rs index a3dff24..df5fc96 100644 --- a/pallets/account-linker/src/mock.rs +++ b/pallets/account-linker/src/mock.rs @@ -1,13 +1,15 @@ use crate::{Module, Trait}; -use sp_core::H256; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_system as system; +use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, testing::Header, Perbill, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, }; -use frame_system as system; impl_outer_origin! { - pub enum Origin for Test {} + pub enum Origin for Test {} } // Configure a mock runtime to test the pallet. @@ -15,47 +17,50 @@ impl_outer_origin! { #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl system::Trait for Test { - type BaseCallFilter = (); - type Origin = Origin; - type Call = (); - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - type PalletInfo = (); - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); + type BaseCallFilter = (); + type Origin = Origin; + type Call = (); + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type PalletInfo = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); } impl Trait for Test { - type Event = (); + type Event = (); } pub type TemplateModule = Module; // Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { - system::GenesisConfig::default().build_storage::().unwrap().into() + system::GenesisConfig::default() + .build_storage::() + .unwrap() + .into() } diff --git a/pallets/account-linker/src/tests.rs b/pallets/account-linker/src/tests.rs index 4443253..66908cd 100644 --- a/pallets/account-linker/src/tests.rs +++ b/pallets/account-linker/src/tests.rs @@ -1,5 +1,5 @@ -use crate::{Error, mock::*}; -use frame_support::{assert_ok, assert_noop}; +use crate::{mock::*, Error}; +use frame_support::{assert_noop, assert_ok}; // #[test] // fn it_works_for_default_value() { diff --git a/pallets/account-linker/src/util.rs b/pallets/account-linker/src/util.rs index c711cff..634530f 100644 --- a/pallets/account-linker/src/util.rs +++ b/pallets/account-linker/src/util.rs @@ -1,10 +1,10 @@ pub fn addr_from_sig(msg: [u8; 32], sig: [u8; 65]) -> Result<[u8; 20], sp_io::EcdsaVerifyError> { - let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig, &msg)?; - let hashed_pk = sp_io::hashing::keccak_256(&pubkey); + let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig, &msg)?; + let hashed_pk = sp_io::hashing::keccak_256(&pubkey); - let mut addr = [0u8; 20]; - addr[..20].copy_from_slice(&hashed_pk[12..32]); - Ok(addr) + let mut addr = [0u8; 20]; + addr[..20].copy_from_slice(&hashed_pk[12..32]); + Ok(addr) } #[cfg(test)] @@ -23,7 +23,6 @@ mod tests { #[test] fn correct_recover() { - let msg = decode("61626364656667").unwrap(); let msg = eth_data_hash(msg); @@ -41,7 +40,6 @@ mod tests { #[test] fn wrong_msg() { - let msg = decode("626364656667").unwrap(); let msg = eth_data_hash(msg); @@ -59,7 +57,6 @@ mod tests { #[test] fn sig_from_another_addr() { - let msg = decode("61626364656667").unwrap(); let msg = eth_data_hash(msg); diff --git a/pallets/offchain-worker/src/lib.rs b/pallets/offchain-worker/src/lib.rs index 90919a0..97b77ac 100644 --- a/pallets/offchain-worker/src/lib.rs +++ b/pallets/offchain-worker/src/lib.rs @@ -1,24 +1,25 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::{prelude::*}; -use frame_system::{ - ensure_signed, ensure_none, - offchain::{CreateSignedTransaction, SubmitTransaction}, -}; use frame_support::{ - debug, dispatch, decl_module, decl_storage, decl_event, decl_error, - ensure, storage::IterableStorageMap, + debug, decl_error, decl_event, decl_module, decl_storage, dispatch, ensure, + storage::IterableStorageMap, +}; +use frame_system::{ + ensure_none, ensure_signed, + offchain::{CreateSignedTransaction, SubmitTransaction}, }; -use sp_core::crypto::KeyTypeId; use lite_json::{self, json::JsonValue}; +use sp_core::crypto::KeyTypeId; +use sp_std::prelude::*; +use codec::Encode; use sp_runtime::{ - transaction_validity::{ - ValidTransaction, InvalidTransaction, TransactionValidity, TransactionSource, TransactionLongevity, - }, + offchain::http, + transaction_validity::{ + InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity, + ValidTransaction, + }, }; -use sp_runtime::offchain::http; -use codec::Encode; #[cfg(test)] mod tests; @@ -26,8 +27,10 @@ mod tests; pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"ocw!"); // https://api.etherscan.io/api?module=account&action=balancemulti&address=0x742d35Cc6634C0532925a3b844Bc454e4438f44e,0x742d35Cc6634C0532925a3b844Bc454e4438f44e&tag=latest&apikey=RF71W4Z2RDA7XQD6EN19NGB66C2QD9UPHB -// The link is ETHER_SCAN_PREFIX + 1st Ethereum account + ETHER_SCAN_DELIMITER + 2nd Ethereum account + ... + ETHER_SCAN_POSTFIX + ETHER_SCAN_TOKEN -pub const ETHER_SCAN_PREFIX: &str = "https://api-ropsten.etherscan.io/api?module=account&action=balancemulti&address=0x"; +// The link is ETHER_SCAN_PREFIX + 1st Ethereum account + ETHER_SCAN_DELIMITER + 2nd Ethereum +// account + ... + ETHER_SCAN_POSTFIX + ETHER_SCAN_TOKEN +pub const ETHER_SCAN_PREFIX: &str = + "https://api-ropsten.etherscan.io/api?module=account&action=balancemulti&address=0x"; pub const ETHER_SCAN_DELIMITER: &str = ",0x"; pub const ETHER_SCAN_POSTFIX: &str = "&tag=latest&apikey="; pub const ETHER_SCAN_TOKEN: &str = "RF71W4Z2RDA7XQD6EN19NGB66C2QD9UPHB"; @@ -35,362 +38,372 @@ pub const ETHER_SCAN_TOKEN: &str = "RF71W4Z2RDA7XQD6EN19NGB66C2QD9UPHB"; pub const SAMPLE_ACCOUNT: &str = "742d35Cc6634C0532925a3b844Bc454e4438f44e"; pub mod crypto { - use super::KEY_TYPE; - use sp_runtime::{ - app_crypto::{app_crypto, sr25519}, - traits::Verify, - }; - use sp_core::sr25519::Signature as Sr25519Signature; - app_crypto!(sr25519, KEY_TYPE); - - pub struct TestAuthId; - impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> for TestAuthId { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } + use super::KEY_TYPE; + use sp_core::sr25519::Signature as Sr25519Signature; + use sp_runtime::{ + app_crypto::{app_crypto, sr25519}, + traits::Verify, + }; + app_crypto!(sr25519, KEY_TYPE); + + pub struct TestAuthId; + impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> + for TestAuthId + { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } } -pub trait Trait: frame_system::Trait + account_linker::Trait + CreateSignedTransaction> { - type Event: From> + Into<::Event>; - type Call: From>; +pub trait Trait: + frame_system::Trait + account_linker::Trait + CreateSignedTransaction> +{ + type Event: From> + Into<::Event>; + type Call: From>; } decl_storage! { - trait Store for Module as OffchainWorkerModule { - /// Record how many claims from Litentry user - TotalClaims get(fn total_claims): u64; - /// Record the accounts send claims in latest block - ClaimAccountSet get(fn query_account_set): map hasher(blake2_128_concat) T::AccountId => (); - /// Record account's ethereum balance - AccountBalance get(fn account_balance): map hasher(blake2_128_concat) T::AccountId => u64; - } + trait Store for Module as OffchainWorkerModule { + /// Record how many claims from Litentry user + TotalClaims get(fn total_claims): u64; + /// Record the accounts send claims in latest block + ClaimAccountSet get(fn query_account_set): map hasher(blake2_128_concat) T::AccountId => (); + /// Record account's ethereum balance + AccountBalance get(fn account_balance): map hasher(blake2_128_concat) T::AccountId => u64; + } } decl_event!( - pub enum Event where AccountId = ::AccountId, - BlockNumber = ::BlockNumber, { - /// Event for account and its ethereum balance - BalanceGot(AccountId, BlockNumber, u64), - } + pub enum Event + where + AccountId = ::AccountId, + BlockNumber = ::BlockNumber, + { + /// Event for account and its ethereum balance + BalanceGot(AccountId, BlockNumber, u64), + } ); // Errors inform users that something went wrong. decl_error! { - pub enum Error for Module { - /// Error names should be descriptive. - NoneValue, - /// Error number parsing. - InvalidNumber - } + pub enum Error for Module { + /// Error names should be descriptive. + NoneValue, + /// Error number parsing. + InvalidNumber + } } // Dispatchable functions allows users to interact with the pallet and invoke state changes. // These functions materialize as "extrinsics", which are often compared to transactions. // Dispatchable functions must be annotated with a weight and must return a DispatchResult. decl_module! { - pub struct Module for enum Call where origin: T::Origin { - // Errors must be initialized if they are used by the pallet. - type Error = Error; - - // Events must be initialized if they are used by the pallet. - fn deposit_event() = default; - - #[weight = 10_000] - pub fn asset_claim(origin,) -> dispatch::DispatchResult { - let account = ensure_signed(origin)?; - - ensure!(!ClaimAccountSet::::contains_key(&account), Error::::InvalidNumber); - - >::insert(&account, ()); - Ok(()) - } - - #[weight = 10_000] - pub fn clear_claim(origin, block: T::BlockNumber)-> dispatch::DispatchResult { - // Ensuring this is an unsigned tx - ensure_none(origin)?; - // Remove all claimed accounts - >::remove_all(); - - Ok(()) - } - - #[weight = 10_000] - pub fn record_balance( - origin, - account: T::AccountId, - block: T::BlockNumber, - balance: u64 - ) -> dispatch::DispatchResult { - // Ensuring this is an unsigned tx - ensure_none(origin)?; - // Record the total claims processed - TotalClaims::put(Self::total_claims() + 1); - // Set balance - >::insert(account.clone(), balance); - // Spit out an event and Add to storage - Self::deposit_event(RawEvent::BalanceGot(account, block, balance)); - - Ok(()) - } - - // Trigger by offchain framework in each block - fn offchain_worker(block: T::BlockNumber) { - // Get the all accounts who ask for asset claims - let accounts: Vec = >::iter().map(|(k, _)| k).collect(); - // Remove all claimed accounts - // TODO seems it doesn't work here to update ClaimAccountSet - // >::remove_all(); - - // Try to remove claims via tx - if accounts.len() > 0 { - let call = Call::clear_claim(block); - let _ = SubmitTransaction::>::submit_unsigned_transaction(call.into()) - .map_err(|_| { - debug::error!("Failed in offchain_unsigned_tx"); - >::InvalidNumber - }); - } - - match Self::fetch_etherscan(accounts, block) { - Ok(()) => debug::info!("Offchain Worker end successfully."), - Err(err) => debug::info!("Offchain Worker end with err {:?}.", err), - } - } - } + pub struct Module for enum Call where origin: T::Origin { + // Errors must be initialized if they are used by the pallet. + type Error = Error; + + // Events must be initialized if they are used by the pallet. + fn deposit_event() = default; + + #[weight = 10_000] + pub fn asset_claim(origin,) -> dispatch::DispatchResult { + let account = ensure_signed(origin)?; + + ensure!(!ClaimAccountSet::::contains_key(&account), Error::::InvalidNumber); + + >::insert(&account, ()); + Ok(()) + } + + #[weight = 10_000] + pub fn clear_claim(origin, block: T::BlockNumber)-> dispatch::DispatchResult { + // Ensuring this is an unsigned tx + ensure_none(origin)?; + // Remove all claimed accounts + >::remove_all(); + + Ok(()) + } + + #[weight = 10_000] + pub fn record_balance( + origin, + account: T::AccountId, + block: T::BlockNumber, + balance: u64 + ) -> dispatch::DispatchResult { + // Ensuring this is an unsigned tx + ensure_none(origin)?; + // Record the total claims processed + TotalClaims::put(Self::total_claims() + 1); + // Set balance + >::insert(account.clone(), balance); + // Spit out an event and Add to storage + Self::deposit_event(RawEvent::BalanceGot(account, block, balance)); + + Ok(()) + } + + // Trigger by offchain framework in each block + fn offchain_worker(block: T::BlockNumber) { + // Get the all accounts who ask for asset claims + let accounts: Vec = >::iter().map(|(k, _)| k).collect(); + // Remove all claimed accounts + // TODO seems it doesn't work here to update ClaimAccountSet + // >::remove_all(); + + // Try to remove claims via tx + if accounts.len() > 0 { + let call = Call::clear_claim(block); + let _ = SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|_| { + debug::error!("Failed in offchain_unsigned_tx"); + >::InvalidNumber + }); + } + + match Self::fetch_etherscan(accounts, block) { + Ok(()) => debug::info!("Offchain Worker end successfully."), + Err(err) => debug::info!("Offchain Worker end with err {:?}.", err), + } + } + } } impl Module { - // Fetch all claimed accounts - fn fetch_etherscan(account_vec: Vec, block: T::BlockNumber) -> Result<(), Error> { - for (_, account) in account_vec.iter().enumerate() { - Self::fetch_etherscan_account(account, block)?; - } - Ok(()) - } - - // fetch an account - fn fetch_etherscan_account(account: &T::AccountId, block: T::BlockNumber) -> Result<(), Error> { - // Get all ethereum accounts linked to Litentry - let eth_accounts = >::get(account); - - // Return if no ethereum account linked - if eth_accounts.len() == 0 { - return Ok(()) - } - - // Compose the web link - let mut link: Vec = Vec::new(); - link.extend(ETHER_SCAN_PREFIX.as_bytes()); - - for (i, eth_account) in eth_accounts.iter().enumerate() { - // Append delimiter if there are more than one accounts in the account_vec - if i >=1 { - link.extend(ETHER_SCAN_DELIMITER.as_bytes()); - }; - - link.extend(Self::address_to_string(eth_account)); - } - link.extend(ETHER_SCAN_POSTFIX.as_bytes()); - link.extend(ETHER_SCAN_TOKEN.as_bytes()); - - // Get the json - let result = Self::fetch_json(&link[..]).map_err(|_| Error::::InvalidNumber)?; - - let response = sp_std::str::from_utf8(&result).map_err(|_| Error::::InvalidNumber)?; - let balances = Self::parse_multi_balances(response); - - match balances { - Some(data) => { - let mut total_balance: u64 = 0; - for item in data { - let balance = Self::chars_to_u64(item).map_err(|_| Error::::InvalidNumber)?; - total_balance = total_balance + balance; - } - let call = Call::record_balance(account.clone(), block, total_balance); - let _ = SubmitTransaction::>::submit_unsigned_transaction(call.into()) - .map_err(|_| { - debug::error!("Failed in offchain_unsigned_tx"); - >::InvalidNumber - }); - }, - None => (), - } - Ok(()) - } - - // Fetch json result from remote URL - fn fetch_json<'a>(remote_url: &'a [u8]) -> Result, &'static str> { - let remote_url_str = core::str::from_utf8(remote_url) - .map_err(|_| "Error in converting remote_url to string")?; - - debug::info!("Offchain Worker request url is {}.", remote_url_str); - let pending = http::Request::get(remote_url_str).send() - .map_err(|_| "Error in sending http GET request")?; - - let response = pending.wait() - .map_err(|_| "Error in waiting http response back")?; - - if response.code != 200 { - debug::warn!("Unexpected status code: {}", response.code); - return Err("Non-200 status code returned from http request"); - } - - let json_result: Vec = response.body().collect::>(); - - let balance = - core::str::from_utf8(&json_result).map_err(|_| "JSON result cannot convert to string")?; - - Ok(balance.as_bytes().to_vec()) - } - - // Parse the balance from ethscan response - fn parse_multi_balances(price_str: &str) -> Option>> { - // { - // "status": "1", - // "message": "OK", - // "result": - // [ - // {"account":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e","balance":"3804372455842738500000001"}, - // {"account":"0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8","balance":"2571179226430511381996287"} - // ] - // } - let val = lite_json::parse_json(price_str); - let mut balance_vec: Vec> = Vec::new(); - - let balances = val.ok().and_then(|v| { - match v { - JsonValue::Object(obj) => { - obj.into_iter() - .find(|(k, _)| { - let mut chars = "result".chars(); - k.iter().all(|k| Some(*k) == chars.next()) - }) - .and_then(|v| { - match v.1 { - JsonValue::Array(res_array) => { - for element in res_array { - match element { - JsonValue::Object(element_vec) => { - for pair in element_vec { - let mut balance_chars = "balance".chars(); - if pair.0.iter().all(|k| Some(*k) == balance_chars.next()) { - match pair.1 { - JsonValue::String(balance) => balance_vec.push(balance), - _ => (), - } - } - }; - }, - _ => () - } - } - Some(balance_vec) - }, - _ => None, - } - }) - }, - _ => None - } - })?; - - Some(balances) - } - - // Parse a single balance from ethscan respose - fn parse_balance(price_str: &str) -> Option> { - // { - // "status": "1", - // "message": "OK", - // "result": "3795858430482738500000001" - // } - let val = lite_json::parse_json(price_str); - let balance = val.ok().and_then(|v| match v { - JsonValue::Object(obj) => { - obj.into_iter() - .find(|(k, _)| { - let mut chars = "result".chars(); - k.iter().all(|k| Some(*k) == chars.next()) - }) - .and_then(|v| match v.1 { - JsonValue::String(balance) => Some(balance), - _ => None, - }) - }, - _ => None - })?; - Some(balance) - } - - // U64 number string to u64 - pub fn chars_to_u64(vec: Vec) -> Result { - let mut result: u64 = 0; - for item in vec { - let n = item.to_digit(10); - match n { - Some(i) => { - let i_64 = i as u64; - result = result * 10 + i_64; - if result < i_64 { - return Err("Wrong u64 balance data format"); - } - }, - None => return Err("Wrong u64 balance data format"), - } - } - return Ok(result) - } - - // number byte to string byte - fn u8_to_str_byte(a: u8) -> u8{ - if a < 10 { - return a + 48 as u8; - } - else { - return a + 87 as u8; - } - } - - // address to string bytes - fn address_to_string(address: &[u8; 20]) -> Vec { - - let mut vec_result: Vec = Vec::new(); - for item in address { - let a: u8 = item & 0x0F; - let b: u8 = item >> 4; - vec_result.push(Self::u8_to_str_byte(b)); - vec_result.push(Self::u8_to_str_byte(a)); - } - return vec_result; - } + // Fetch all claimed accounts + fn fetch_etherscan( + account_vec: Vec, + block: T::BlockNumber, + ) -> Result<(), Error> { + for (_, account) in account_vec.iter().enumerate() { + Self::fetch_etherscan_account(account, block)?; + } + Ok(()) + } + + // fetch an account + fn fetch_etherscan_account( + account: &T::AccountId, + block: T::BlockNumber, + ) -> Result<(), Error> { + // Get all ethereum accounts linked to Litentry + let eth_accounts = >::get(account); + + // Return if no ethereum account linked + if eth_accounts.len() == 0 { + return Ok(()); + } + + // Compose the web link + let mut link: Vec = Vec::new(); + link.extend(ETHER_SCAN_PREFIX.as_bytes()); + + for (i, eth_account) in eth_accounts.iter().enumerate() { + // Append delimiter if there are more than one accounts in the account_vec + if i >= 1 { + link.extend(ETHER_SCAN_DELIMITER.as_bytes()); + }; + + link.extend(Self::address_to_string(eth_account)); + } + link.extend(ETHER_SCAN_POSTFIX.as_bytes()); + link.extend(ETHER_SCAN_TOKEN.as_bytes()); + + // Get the json + let result = Self::fetch_json(&link[..]).map_err(|_| Error::::InvalidNumber)?; + + let response = sp_std::str::from_utf8(&result).map_err(|_| Error::::InvalidNumber)?; + let balances = Self::parse_multi_balances(response); + + match balances { + Some(data) => { + let mut total_balance: u64 = 0; + for item in data { + let balance = + Self::chars_to_u64(item).map_err(|_| Error::::InvalidNumber)?; + total_balance = total_balance + balance; + } + let call = Call::record_balance(account.clone(), block, total_balance); + let _ = SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|_| { + debug::error!("Failed in offchain_unsigned_tx"); + >::InvalidNumber + }); + } + None => (), + } + Ok(()) + } + + // Fetch json result from remote URL + fn fetch_json<'a>(remote_url: &'a [u8]) -> Result, &'static str> { + let remote_url_str = core::str::from_utf8(remote_url) + .map_err(|_| "Error in converting remote_url to string")?; + + debug::info!("Offchain Worker request url is {}.", remote_url_str); + let pending = http::Request::get(remote_url_str) + .send() + .map_err(|_| "Error in sending http GET request")?; + + let response = pending + .wait() + .map_err(|_| "Error in waiting http response back")?; + + if response.code != 200 { + debug::warn!("Unexpected status code: {}", response.code); + return Err("Non-200 status code returned from http request"); + } + + let json_result: Vec = response.body().collect::>(); + + let balance = core::str::from_utf8(&json_result) + .map_err(|_| "JSON result cannot convert to string")?; + + Ok(balance.as_bytes().to_vec()) + } + + // Parse the balance from ethscan response + fn parse_multi_balances(price_str: &str) -> Option>> { + // { + // "status": "1", + // "message": "OK", + // "result": + // [ + // {"account":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e","balance":" + // 3804372455842738500000001"}, {"account":" + // 0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8","balance":"2571179226430511381996287"} + // ] + // } + let val = lite_json::parse_json(price_str); + let mut balance_vec: Vec> = Vec::new(); + + let balances = val.ok().and_then(|v| match v { + JsonValue::Object(obj) => obj + .into_iter() + .find(|(k, _)| { + let mut chars = "result".chars(); + k.iter().all(|k| Some(*k) == chars.next()) + }) + .and_then(|v| match v.1 { + JsonValue::Array(res_array) => { + for element in res_array { + match element { + JsonValue::Object(element_vec) => { + for pair in element_vec { + let mut balance_chars = "balance".chars(); + if pair.0.iter().all(|k| Some(*k) == balance_chars.next()) { + match pair.1 { + JsonValue::String(balance) => { + balance_vec.push(balance) + } + _ => (), + } + } + } + } + _ => (), + } + } + Some(balance_vec) + } + _ => None, + }), + _ => None, + })?; + + Some(balances) + } + + // Parse a single balance from ethscan respose + fn parse_balance(price_str: &str) -> Option> { + // { + // "status": "1", + // "message": "OK", + // "result": "3795858430482738500000001" + // } + let val = lite_json::parse_json(price_str); + let balance = val.ok().and_then(|v| match v { + JsonValue::Object(obj) => obj + .into_iter() + .find(|(k, _)| { + let mut chars = "result".chars(); + k.iter().all(|k| Some(*k) == chars.next()) + }) + .and_then(|v| match v.1 { + JsonValue::String(balance) => Some(balance), + _ => None, + }), + _ => None, + })?; + Some(balance) + } + + // U64 number string to u64 + pub fn chars_to_u64(vec: Vec) -> Result { + let mut result: u64 = 0; + for item in vec { + let n = item.to_digit(10); + match n { + Some(i) => { + let i_64 = i as u64; + result = result * 10 + i_64; + if result < i_64 { + return Err("Wrong u64 balance data format"); + } + } + None => return Err("Wrong u64 balance data format"), + } + } + return Ok(result); + } + + // number byte to string byte + fn u8_to_str_byte(a: u8) -> u8 { + if a < 10 { + return a + 48 as u8; + } else { + return a + 87 as u8; + } + } + + // address to string bytes + fn address_to_string(address: &[u8; 20]) -> Vec { + let mut vec_result: Vec = Vec::new(); + for item in address { + let a: u8 = item & 0x0F; + let b: u8 = item >> 4; + vec_result.push(Self::u8_to_str_byte(b)); + vec_result.push(Self::u8_to_str_byte(a)); + } + return vec_result; + } } #[allow(deprecated)] impl frame_support::unsigned::ValidateUnsigned for Module { - type Call = Call; - - #[allow(deprecated)] - fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - - match call { - Call::record_balance(account, block, price) => Ok(ValidTransaction { - priority: 0, - requires: vec![], - provides: vec![(account, block, price).encode()], - longevity: TransactionLongevity::max_value(), - propagate: true, - }), - - Call::clear_claim(block) => Ok(ValidTransaction { - priority: 0, - requires: vec![], - provides: vec![(block).encode()], - longevity: TransactionLongevity::max_value(), - propagate: true, - }), - _ => InvalidTransaction::Call.into() - } - } -} \ No newline at end of file + type Call = Call; + + #[allow(deprecated)] + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match call { + Call::record_balance(account, block, price) => Ok(ValidTransaction { + priority: 0, + requires: vec![], + provides: vec![(account, block, price).encode()], + longevity: TransactionLongevity::max_value(), + propagate: true, + }), + + Call::clear_claim(block) => Ok(ValidTransaction { + priority: 0, + requires: vec![], + provides: vec![(block).encode()], + longevity: TransactionLongevity::max_value(), + propagate: true, + }), + _ => InvalidTransaction::Call.into(), + } + } +} diff --git a/pallets/offchain-worker/src/tests.rs b/pallets/offchain-worker/src/tests.rs index 5fc5c75..b6dc1ff 100644 --- a/pallets/offchain-worker/src/tests.rs +++ b/pallets/offchain-worker/src/tests.rs @@ -1,122 +1,122 @@ use crate::*; -use frame_support::{impl_outer_event, impl_outer_origin, parameter_types}; use codec::{alloc::sync::Arc, Decode}; +use frame_support::{impl_outer_event, impl_outer_origin, parameter_types}; use parking_lot::RwLock; use sp_core::{ - offchain::{ - testing::{self, OffchainState, PoolState}, - OffchainExt, TransactionPoolExt, - }, - sr25519::{self, Signature}, - testing::KeyStore, - traits::KeystoreExt, - H256, + offchain::{ + testing::{self, OffchainState, PoolState}, + OffchainExt, TransactionPoolExt, + }, + sr25519::{self, Signature}, + testing::KeyStore, + traits::KeystoreExt, + H256, }; use sp_io::TestExternalities; use sp_runtime::{ - testing::{Header, TestXt}, - traits::{BlakeTwo256, IdentityLookup, Verify}, - Perbill, + testing::{Header, TestXt}, + traits::{BlakeTwo256, IdentityLookup, Verify}, + Perbill, }; use crate as OffchainWorker; use account_linker; impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} + pub enum Origin for TestRuntime where system = frame_system {} } impl_outer_event! { - pub enum TestEvent for TestRuntime { - frame_system, - OffchainWorker, - account_linker, - } + pub enum TestEvent for TestRuntime { + frame_system, + OffchainWorker, + account_linker, + } } #[derive(Clone, PartialEq, Eq, Debug)] pub struct TestRuntime; parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1_000_000; - pub const MaximumBlockLength: u32 = 10 * 1_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1_000_000; + pub const MaximumBlockLength: u32 = 10 * 1_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::one(); } // The TestRuntime implements two pallet/frame traits: system, and simple_event impl frame_system::Trait for TestRuntime { - type BaseCallFilter = (); - type Origin = Origin; - type Index = u64; - type Call = (); - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = sr25519::Public; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - type PalletInfo = (); - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); + type BaseCallFilter = (); + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = sr25519::Public; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type PalletInfo = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); } pub type TestExtrinsic = TestXt, ()>; parameter_types! { - pub const UnsignedPriority: u64 = 100; + pub const UnsignedPriority: u64 = 100; } impl Trait for TestRuntime { - // type AuthorityId = crypto::TestAuthId; - type Call = Call; - type Event = TestEvent; + // type AuthorityId = crypto::TestAuthId; + type Call = Call; + type Event = TestEvent; } impl account_linker::Trait for TestRuntime { - type Event = TestEvent; + type Event = TestEvent; } impl frame_system::offchain::CreateSignedTransaction for TestRuntime where - Call: From, + Call: From, { - fn create_transaction>( - call: Call, - _public: ::Signer, - _account: ::AccountId, - index: ::Index, - ) -> Option<( - Call, - ::SignaturePayload, - )> { - Some((call, (index, ()))) - } + fn create_transaction>( + call: Call, + _public: ::Signer, + _account: ::AccountId, + index: ::Index, + ) -> Option<( + Call, + ::SignaturePayload, + )> { + Some((call, (index, ()))) + } } impl frame_system::offchain::SigningTypes for TestRuntime { - type Public = ::Signer; - type Signature = Signature; + type Public = ::Signer; + type Signature = Signature; } impl frame_system::offchain::SendTransactionTypes for TestRuntime where - Call: From, + Call: From, { - type OverarchingCall = Call; - type Extrinsic = TestExtrinsic; + type OverarchingCall = Call; + type Extrinsic = TestExtrinsic; } pub type System = frame_system::Module; @@ -125,48 +125,56 @@ pub type System = frame_system::Module; pub struct ExternalityBuilder; impl ExternalityBuilder { - pub fn build() -> ( - TestExternalities, - Arc>, - Arc>, - ) { - const PHRASE: &str = - "expire stage crawl shell boss any story swamp skull yellow bamboo copy"; - - let (offchain, offchain_state) = testing::TestOffchainExt::new(); - let (pool, pool_state) = testing::TestTransactionPoolExt::new(); - let keystore = KeyStore::new(); - keystore - .write() - .sr25519_generate_new(KEY_TYPE, Some(&format!("{}/hunter1", PHRASE))) - .unwrap(); - - let storage = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - let mut t = TestExternalities::from(storage); - t.register_extension(OffchainExt::new(offchain)); - t.register_extension(TransactionPoolExt::new(pool)); - t.register_extension(KeystoreExt(keystore)); - t.execute_with(|| System::set_block_number(1)); - (t, pool_state, offchain_state) - } + pub fn build() -> ( + TestExternalities, + Arc>, + Arc>, + ) { + const PHRASE: &str = + "expire stage crawl shell boss any story swamp skull yellow bamboo copy"; + + let (offchain, offchain_state) = testing::TestOffchainExt::new(); + let (pool, pool_state) = testing::TestTransactionPoolExt::new(); + let keystore = KeyStore::new(); + keystore + .write() + .sr25519_generate_new(KEY_TYPE, Some(&format!("{}/hunter1", PHRASE))) + .unwrap(); + + let storage = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + let mut t = TestExternalities::from(storage); + t.register_extension(OffchainExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(keystore)); + t.execute_with(|| System::set_block_number(1)); + (t, pool_state, offchain_state) + } } #[test] fn test_chars_to_u64() { - let correct_balance = vec!['5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']; - - assert_eq!(Ok(500000000000000000), >::chars_to_u64(correct_balance)); - - let correct_balance = vec!['a', '2']; - assert_eq!(Err("Wrong u64 balance data format"), >::chars_to_u64(correct_balance)); + let correct_balance = vec![ + '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', + ]; + + assert_eq!( + Ok(500000000000000000), + >::chars_to_u64(correct_balance) + ); + + let correct_balance = vec!['a', '2']; + assert_eq!( + Err("Wrong u64 balance data format"), + >::chars_to_u64(correct_balance) + ); } #[test] fn test_parse_multi_balances() { - let double_balances = r#" + let double_balances = r#" { "status": "1", "message": "OK", @@ -176,19 +184,24 @@ fn test_parse_multi_balances() { {"account":"0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8","balance":"21"} ] }"#; - assert_eq!(Some(vec![vec!['1', '2'], vec!['2', '1']]), >::parse_multi_balances(double_balances)); + assert_eq!( + Some(vec![vec!['1', '2'], vec!['2', '1']]), + >::parse_multi_balances(double_balances) + ); } #[test] fn test_parse_balance() { - - let balance = r#" + let balance = r#" { "status": "1", "message": "OK", "result": "12" }"#; - assert_eq!(Some(vec!['1', '2']), >::parse_balance(balance)); + assert_eq!( + Some(vec!['1', '2']), + >::parse_balance(balance) + ); } // #[test] diff --git a/runtime/build.rs b/runtime/build.rs index 5270504..9e6ce72 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -1,10 +1,10 @@ use wasm_builder_runner::WasmBuilder; fn main() { - WasmBuilder::new() - .with_current_project() - .with_wasm_builder_from_crates("2.0.0") - .export_heap_base() - .import_memory() - .build() + WasmBuilder::new() + .with_current_project() + .with_wasm_builder_from_crates("2.0.0") + .export_heap_base() + .import_memory() + .build() } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 89218b1..cf39a0a 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,43 +1,46 @@ #![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, Encode}; -use sp_runtime::{ - ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature, - transaction_validity::{TransactionValidity, TransactionSource}, -}; -use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating, - SaturatedConversion, +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; -use pallet_grandpa::fg_primitives; -use sp_version::RuntimeVersion; +use sp_core::{crypto::KeyTypeId, Encode, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, + SaturatedConversion, Saturating, Verify, + }, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; +use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; +use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use pallet_timestamp::Call as TimestampCall; -pub use pallet_balances::Call as BalancesCall; -pub use sp_runtime::{Permill, Perbill}; pub use frame_support::{ - construct_runtime, parameter_types, StorageValue, debug, - traits::{KeyOwnerProofSystem, Randomness}, - weights::{ - Weight, IdentityFee, - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - }, + construct_runtime, debug, parameter_types, + traits::{KeyOwnerProofSystem, Randomness}, + weights::{ + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + IdentityFee, Weight, + }, + StorageValue, }; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; /// Import the template pallet. pub use pallet_account_linker; @@ -76,33 +79,33 @@ pub type DigestItem = generic::DigestItem; /// 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; - - /// 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; - - impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - pub grandpa: Grandpa, - } - } + 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; + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } + } } pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("litentry-node"), - impl_name: create_runtime_str!("litentry-node"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, + spec_name: create_runtime_str!("litentry-node"), + impl_name: create_runtime_str!("litentry-node"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, }; pub const MILLISECS_PER_BLOCK: u64 = 6000; @@ -117,157 +120,157 @@ pub const DAYS: BlockNumber = HOURS * 24; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } } parameter_types! { - pub const BlockHashCount: BlockNumber = 2400; - /// We allow for 2 seconds of compute with a 6 second average block time. - pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - /// Assume 10% of weight for average on_initialize calls. - pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() - .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; - pub const Version: RuntimeVersion = VERSION; + pub const BlockHashCount: BlockNumber = 2400; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; } // Configure FRAME pallets to include in runtime. impl frame_system::Trait for Runtime { - /// The basic call filter to use in dispatchable. - type BaseCallFilter = (); - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type Call = Call; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = IdentityLookup; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The index type for blocks. - type BlockNumber = BlockNumber; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = BlakeTwo256; - /// The header type. - type Header = generic::Header; - /// The ubiquitous event type. - type Event = Event; - /// The ubiquitous origin type. - type Origin = Origin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Maximum weight of each block. - type MaximumBlockWeight = MaximumBlockWeight; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The weight of the overhead invoked on the block import process, independent of the - /// extrinsics included in that block. - type BlockExecutionWeight = BlockExecutionWeight; - /// The base weight of any extrinsic processed by the runtime, independent of the - /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; - /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, - /// idependent of the logic of that extrinsics. (Roughly max block weight - average on - /// initialize cost). - type MaximumExtrinsicWeight = MaximumExtrinsicWeight; - /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. - type MaximumBlockLength = MaximumBlockLength; - /// Portion of the block weight that is available to all normal transactions. - type AvailableBlockRatio = AvailableBlockRatio; - /// Version of the runtime. - type Version = Version; - /// Converts a module to the index of the module in `construct_runtime!`. - /// - /// This type is being generated by `construct_runtime!`. - type PalletInfo = PalletInfo; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Maximum weight of each block. + type MaximumBlockWeight = MaximumBlockWeight; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The weight of the overhead invoked on the block import process, independent of the + /// extrinsics included in that block. + type BlockExecutionWeight = BlockExecutionWeight; + /// The base weight of any extrinsic processed by the runtime, independent of the + /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, + /// idependent of the logic of that extrinsics. (Roughly max block weight - average on + /// initialize cost). + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type MaximumBlockLength = MaximumBlockLength; + /// Portion of the block weight that is available to all normal transactions. + type AvailableBlockRatio = AvailableBlockRatio; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); } impl pallet_aura::Trait for Runtime { - type AuthorityId = AuraId; + type AuthorityId = AuraId; } impl pallet_grandpa::Trait for Runtime { - type Event = Event; - type Call = Call; + type Event = Event; + type Call = Call; - type KeyOwnerProofSystem = (); + type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; + type KeyOwnerProof = + >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; + type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); + type HandleEquivocation = (); - type WeightInfo = (); + type WeightInfo = (); } parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; } impl pallet_timestamp::Trait for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { - pub const ExistentialDeposit: u128 = 500; - pub const MaxLocks: u32 = 50; + pub const ExistentialDeposit: u128 = 500; + pub const MaxLocks: u32 = 50; } impl pallet_balances::Trait for Runtime { - type MaxLocks = MaxLocks; - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type Event = Event; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); + type MaxLocks = MaxLocks; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); } parameter_types! { - pub const TransactionByteFee: Balance = 1; + pub const TransactionByteFee: Balance = 1; } impl pallet_transaction_payment::Trait for Runtime { - type Currency = Balances; - type OnTransactionPayment = (); - type TransactionByteFee = TransactionByteFee; - type WeightToFee = IdentityFee; - type FeeMultiplierUpdate = (); + type Currency = Balances; + type OnTransactionPayment = (); + type TransactionByteFee = TransactionByteFee; + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = (); } impl pallet_sudo::Trait for Runtime { - type Event = Event; - type Call = Call; + type Event = Event; + type Call = Call; } /// Configure the template pallet in pallets/template. impl pallet_account_linker::Trait for Runtime { - type Event = Event; + type Event = Event; } /// We need to define the Transaction signer for that using the Key definition @@ -279,88 +282,87 @@ impl pallet_account_linker::Trait for Runtime { /// Configure the template pallet in pallets/template. impl pallet_offchain_worker::Trait for Runtime { - type Event = Event; - type Call = Call; - // type SubmitUnsignedTransaction = SubmitPFTransaction; - + type Event = Event; + type Call = Call; + // type SubmitUnsignedTransaction = SubmitPFTransaction; } pub type SignedPayload = generic::SignedPayload; impl frame_system::offchain::CreateSignedTransaction for Runtime where - Call: From, + Call: From, { - fn create_transaction>( - call: Call, - public: ::Signer, - account: AccountId, - index: Index, - ) -> Option<( - Call, - ::SignaturePayload, - )> { - let period = BlockHashCount::get() as u64; - let current_block = System::block_number() - .saturated_into::() - .saturating_sub(1); - let tip = 0; - let extra: SignedExtra = ( - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), - frame_system::CheckNonce::::from(index), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); - - #[cfg_attr(not(feature = "std"), allow(unused_variables))] - let raw_payload = SignedPayload::new(call, extra) - .map_err(|e| { - debug::native::warn!("SignedPayload error: {:?}", e); - }) - .ok()?; - - let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - - let address = account; - let (call, extra, _) = raw_payload.deconstruct(); - Some((call, (address, signature, extra))) - } + fn create_transaction>( + call: Call, + public: ::Signer, + account: AccountId, + index: Index, + ) -> Option<( + Call, + ::SignaturePayload, + )> { + let period = BlockHashCount::get() as u64; + let current_block = System::block_number() + .saturated_into::() + .saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(index), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + ); + + #[cfg_attr(not(feature = "std"), allow(unused_variables))] + let raw_payload = SignedPayload::new(call, extra) + .map_err(|e| { + debug::native::warn!("SignedPayload error: {:?}", e); + }) + .ok()?; + + let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; + + let address = account; + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) + } } impl frame_system::offchain::SigningTypes for Runtime { - type Public = ::Signer; - type Signature = Signature; + type Public = ::Signer; + type Signature = Signature; } impl frame_system::offchain::SendTransactionTypes for Runtime where - Call: From, + Call: From, { - type OverarchingCall = Call; - type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = Call; + type Extrinsic = UncheckedExtrinsic; } // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = opaque::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: frame_system::{Module, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, - Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config, Inherent}, - Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Module, Storage}, - Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, - // Include the custom logic from the template pallet in the runtime. - AccountLinkerModule: pallet_account_linker::{Module, Call, Storage, Event}, - OffchainWorkerModule: pallet_offchain_worker::{Module, Call, Storage, Event, ValidateUnsigned}, - } + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Module, Call, Config, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, + Aura: pallet_aura::{Module, Config, Inherent}, + Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Module, Storage}, + Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, + // Include the custom logic from the template pallet in the runtime. + AccountLinkerModule: pallet_account_linker::{Module, Call, Storage, Event}, + OffchainWorkerModule: pallet_offchain_worker::{Module, Call, Storage, Event, ValidateUnsigned}, + } ); /// The address format for describing accounts. @@ -375,13 +377,13 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; @@ -389,169 +391,169 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllModules, + Runtime, + Block, + frame_system::ChainContext, + 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: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::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 sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> u64 { - Aura::slot_duration() - } - - fn authorities() -> Vec { - Aura::authorities() - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - opaque::SessionKeys::generate(seed) - } - - fn decode_session_keys( - encoded: Vec, - ) -> Option, KeyTypeId)>> { - opaque::SessionKeys::decode_into_raw_public_keys(&encoded) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_authorities() -> GrandpaAuthorityList { - Grandpa::grandpa_authorities() - } - - fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: fg_primitives::EquivocationProof< - ::Hash, - NumberFor, - >, - _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, - ) -> Option<()> { - None - } - - fn generate_key_ownership_proof( - _set_id: fg_primitives::SetId, - _authority_id: GrandpaId, - ) -> Option { - // NOTE: this is the only implementation possible since we've - // defined our key owner proof type as a bottom type (i.e. a type - // with no values). - None - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { - System::account_nonce(account) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { - fn query_info( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; - - use frame_system_benchmarking::Module as SystemBench; - impl frame_system_benchmarking::Trait for Runtime {} - - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Total Issuance - hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - ]; - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); - - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } - Ok(batches) - } - } + 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: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::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 sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { + Aura::slot_duration() + } + + fn authorities() -> Vec { + Aura::authorities() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + + use frame_system_benchmarking::Module as SystemBench; + impl frame_system_benchmarking::Trait for Runtime {} + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + add_benchmark!(params, batches, frame_system, SystemBench::); + add_benchmark!(params, batches, pallet_balances, Balances); + add_benchmark!(params, batches, pallet_timestamp, Timestamp); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } } From f6550317950d90341e192144f631d36e12b90d45 Mon Sep 17 00:00:00 2001 From: "zongxiong.chen" Date: Mon, 23 Nov 2020 21:19:25 +0100 Subject: [PATCH 2/2] Add git-hook and Makefile --- Cargo.toml | 49 +++++++++++++++++++++++++++--- Makefile | 31 +++++++++++++++++++ README.md | 14 ++++++++- node/Cargo.toml | 5 +++ pallets/account-linker/Cargo.toml | 4 +++ pallets/offchain-worker/Cargo.toml | 25 +++++++++------ runtime/Cargo.toml | 5 +++ 7 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 Makefile diff --git a/Cargo.toml b/Cargo.toml index ff23e1f..732c62d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,51 @@ -[profile.release] -panic = 'unwind' - [workspace] members = [ 'node', 'pallets/account-linker', - 'pallets/offchain-worker', + 'pallets/offchain-worker', 'runtime', ] + +[profile.dev] +opt-level = 0 +debug = true +debug-assertions = true +overflow-checks = true +lto = false +panic = 'unwind' +incremental = true +codegen-units = 256 +rpath = false + +[profile.test] +opt-level = 0 +debug = 2 +debug-assertions = true +overflow-checks = true +lto = false +panic = 'unwind' # This setting is always ignored. +incremental = true +codegen-units = 256 +rpath = false + +[profile.bench] +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = false +panic = 'unwind' # This setting is always ignored. +incremental = false +codegen-units = 16 +rpath = false + +[profile.release] +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = false +panic = 'unwind' +incremental = false +codegen-units = 16 +rpath = false diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1f7c64e --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +all: + @echo "Make All" + +build: + cargo build +node: + cargo build --package $(call pkgid, litentry-node) +runtime: + cargo build --package $(call pkgid, litentry-runtime) +offchain-worker: + cargo build --package $(call pkgid, pallet-offchain-worker) +account-linker: + cargo build --package $(call pkgid, pallet-account-linker) + +test-node: + cargo test --package $(call pkgid, litentry-node) +test-runtime: + cargo test --package $(call pkgid, litentry-runtime) +test-account-linker: + cargo test --package $(call pkgid, pallet-account-linker) +test-offchain-worker: + cargo test --package $(call pkgid, pallet-offchain-worker) + +test: + cargo test + +fmt: + cargo fmt +define pkgid + $(shell cargo pkgid $1) +endef diff --git a/README.md b/README.md index d580fa3..50dbbd8 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,16 @@ Litentry node built with Substrate. ## License -Apache-2.0 \ No newline at end of file +Apache-2.0 + + +## Set up + ``` + rustup default nightly-2020-10-06 + ``` + + ``` + cargo build + ``` +## Useful links + [rustfmt configurations](https://github.com/rust-lang/rustfmt/blob/master/Configurations.md) diff --git a/node/Cargo.toml b/node/Cargo.toml index e27c4d3..53f229a 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -55,3 +55,8 @@ substrate-frame-rpc-system = '2.0.0' [features] default = [] runtime-benchmarks = ['litentry-runtime/runtime-benchmarks'] + +[dev-dependencies.cargo-husky] +version = "1" +default-features = false # Disable features which are enabled by default +features = ["precommit-hook", "run-cargo-fmt"] diff --git a/pallets/account-linker/Cargo.toml b/pallets/account-linker/Cargo.toml index 00bc29b..9dfefb0 100644 --- a/pallets/account-linker/Cargo.toml +++ b/pallets/account-linker/Cargo.toml @@ -38,3 +38,7 @@ std = [ "sp-io/std", "sp-std/std", ] +[dev-dependencies.cargo-husky] +version = "1" +default-features = false # Disable features which are enabled by default +features = ["precommit-hook", "run-cargo-fmt"] diff --git a/pallets/offchain-worker/Cargo.toml b/pallets/offchain-worker/Cargo.toml index 9bf180c..b43690d 100644 --- a/pallets/offchain-worker/Cargo.toml +++ b/pallets/offchain-worker/Cargo.toml @@ -35,14 +35,19 @@ sp-runtime = { default-features = false, version = '2.0.0' } default = ['std'] std = [ "codec/std", - "frame-support/std", - "frame-system/std", - "serde", - "lite-json/std", - "sp-core/std", - "sp-io/std", - # "sp-keystore", - "sp-runtime/std", - "sp-std/std", - "account-linker/std", + "frame-support/std", + "frame-system/std", + "serde", + "lite-json/std", + "sp-core/std", + "sp-io/std", + # "sp-keystore", + "sp-runtime/std", + "sp-std/std", + "account-linker/std", ] + +[dev-dependencies.cargo-husky] +version = "1" +default-features = false # Disable features which are enabled by default +features = ["precommit-hook", "run-cargo-fmt"] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index a8cf807..aa4f364 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -96,3 +96,8 @@ std = [ 'sp-transaction-pool/std', 'sp-version/std', ] + +[dev-dependencies.cargo-husky] +version = "1" +default-features = false # Disable features which are enabled by default +features = ["precommit-hook", "run-cargo-fmt"]