mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 20:07:56 +00:00
Squashed commit of Rust-ifying the repo:
commit e31c1965a2e6b9a21ce68be63b81915b2b090f1d Author: Hernando Castano <castano.ha@gmail.com> Date: Sun Feb 2 21:15:42 2020 -0500 Get Ethereum bridge module compiling commit a497fc1640e68682f61b39414ffb15206c6120e2 Author: Hernando Castano <castano.ha@gmail.com> Date: Thu Jan 30 12:15:43 2020 -0500 Make the toml file look a bit better commit 898fb7b06cfac7cf866e1a28fed9a4f02bd246a7 Author: Hernando Castano <castano.ha@gmail.com> Date: Thu Jan 30 12:06:27 2020 -0500 Get substrate bridge module compiling commit 81e1547e6bec9f590cad9ffba0ee5dfa82cda1c1 Author: Hernando Castano <castano.ha@gmail.com> Date: Thu Jan 30 11:40:29 2020 -0500 Create workspace and move more files around
This commit is contained in:
committed by
Bastian Köcher
parent
c06777a42a
commit
fbaa803034
@@ -0,0 +1,128 @@
|
||||
[package]
|
||||
name = "node-cli"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Substrate node implementation in Rust."
|
||||
build = "build.rs"
|
||||
edition = "2018"
|
||||
default-run = "substrate"
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "paritytech/substrate", branch = "master" }
|
||||
maintenance = { status = "actively-developed" }
|
||||
is-it-maintained-issue-resolution = { repository = "paritytech/substrate" }
|
||||
is-it-maintained-open-issues = { repository = "paritytech/substrate" }
|
||||
|
||||
[[bin]]
|
||||
name = "substrate"
|
||||
path = "bin/main.rs"
|
||||
required-features = ["cli"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
# third-party dependencies
|
||||
codec = { package = "parity-scale-codec", version = "1.0.6" }
|
||||
serde = { version = "1.0.102", features = ["derive"] }
|
||||
futures01 = { package = "futures", version = "0.1.29" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
hex-literal = "0.2.1"
|
||||
jsonrpc-core = "14.0.3"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.2"
|
||||
structopt = "=0.3.7"
|
||||
|
||||
# primitives
|
||||
sp-authority-discovery = { version = "2.0.0", path = "../../../primitives/authority-discovery" }
|
||||
sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" }
|
||||
grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" }
|
||||
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
|
||||
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
|
||||
sp-timestamp = { version = "2.0.0", default-features = false, path = "../../../primitives/timestamp" }
|
||||
sp-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../primitives/finality-tracker" }
|
||||
sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" }
|
||||
sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" }
|
||||
sp-io = { version = "2.0.0", path = "../../../primitives/io" }
|
||||
sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" }
|
||||
sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" }
|
||||
|
||||
# client dependencies
|
||||
sc-client-api = { version = "2.0.0", path = "../../../client/api" }
|
||||
sc-client = { version = "2.0.0", path = "../../../client/" }
|
||||
sc-chain-spec = { version = "2.0.0", path = "../../../client/chain-spec" }
|
||||
sc-transaction-pool = { version = "2.0.0", path = "../../../client/transaction-pool" }
|
||||
sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" }
|
||||
sc-network = { version = "0.8", path = "../../../client/network" }
|
||||
sc-consensus-babe = { version = "0.8", path = "../../../client/consensus/babe" }
|
||||
grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" }
|
||||
sc-client-db = { version = "2.0.0", default-features = false, path = "../../../client/db" }
|
||||
sc-offchain = { version = "2.0.0", path = "../../../client/offchain" }
|
||||
sc-rpc = { version = "2.0.0", path = "../../../client/rpc" }
|
||||
sc-basic-authority = { version = "2.0.0", path = "../../../client/basic-authorship" }
|
||||
sc-service = { version = "2.0.0", default-features = false, path = "../../../client/service" }
|
||||
sc-telemetry = { version = "2.0.0", path = "../../../client/telemetry" }
|
||||
sc-authority-discovery = { version = "2.0.0", path = "../../../client/authority-discovery" }
|
||||
|
||||
# frame dependencies
|
||||
pallet-indices = { version = "2.0.0", path = "../../../frame/indices" }
|
||||
pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" }
|
||||
pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" }
|
||||
frame-system = { version = "2.0.0", path = "../../../frame/system" }
|
||||
pallet-balances = { version = "2.0.0", path = "../../../frame/balances" }
|
||||
pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" }
|
||||
frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" }
|
||||
pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" }
|
||||
pallet-authority-discovery = { version = "2.0.0", path = "../../../frame/authority-discovery" }
|
||||
|
||||
# node-specific dependencies
|
||||
node-runtime = { version = "2.0.0", path = "../runtime" }
|
||||
node-rpc = { version = "2.0.0", path = "../rpc" }
|
||||
node-primitives = { version = "2.0.0", path = "../primitives" }
|
||||
node-executor = { version = "2.0.0", path = "../executor" }
|
||||
|
||||
# CLI-specific dependencies
|
||||
tokio = { version = "0.1.22", optional = true }
|
||||
sc-cli = { version = "2.0.0", optional = true, path = "../../../client/cli" }
|
||||
ctrlc = { version = "3.1.3", features = ["termination"], optional = true }
|
||||
node-transaction-factory = { version = "2.0.0", optional = true, path = "../transaction-factory" }
|
||||
|
||||
# WASM-specific dependencies
|
||||
wasm-bindgen = { version = "0.2.57", optional = true }
|
||||
wasm-bindgen-futures = { version = "0.4.7", optional = true }
|
||||
browser-utils = { path = "../../../utils/browser", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
sc-keystore = { version = "2.0.0", path = "../../../client/keystore" }
|
||||
sc-consensus-babe = { version = "0.8", features = ["test-helpers"], path = "../../../client/consensus/babe" }
|
||||
sc-service-test = { version = "2.0.0", path = "../../../client/service/test" }
|
||||
futures = "0.3.1"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
sc-cli = { version = "2.0.0", package = "sc-cli", path = "../../../client/cli" }
|
||||
build-script-utils = { version = "2.0.0", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" }
|
||||
structopt = "=0.3.7"
|
||||
vergen = "3.0.4"
|
||||
|
||||
[features]
|
||||
default = ["cli", "wasmtime"]
|
||||
browser = [
|
||||
"browser-utils",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
cli = [
|
||||
"sc-cli",
|
||||
"node-transaction-factory",
|
||||
"tokio",
|
||||
"ctrlc",
|
||||
"sc-service/rocksdb",
|
||||
"node-executor/wasmi-errno",
|
||||
]
|
||||
wasmtime = [
|
||||
"cli",
|
||||
"node-executor/wasmtime",
|
||||
"sc-cli/wasmtime",
|
||||
"sc-service/wasmtime",
|
||||
]
|
||||
@@ -0,0 +1,449 @@
|
||||
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate chain configurations.
|
||||
|
||||
use sc_chain_spec::ChainSpecExtension;
|
||||
use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use node_runtime::{
|
||||
AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig,
|
||||
GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig,
|
||||
SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, BridgeEthPoaConfig,
|
||||
};
|
||||
use node_runtime::Block;
|
||||
use node_runtime::constants::currency::*;
|
||||
use sc_service;
|
||||
use hex_literal::hex;
|
||||
use sc_telemetry::TelemetryEndpoints;
|
||||
use grandpa_primitives::{AuthorityId as GrandpaId};
|
||||
use sp_consensus_babe::{AuthorityId as BabeId};
|
||||
use pallet_im_online::sr25519::{AuthorityId as ImOnlineId};
|
||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use sp_runtime::{Perbill, traits::{Verify, IdentifyAccount}};
|
||||
|
||||
pub use node_primitives::{AccountId, Balance, Signature};
|
||||
pub use node_runtime::GenesisConfig;
|
||||
|
||||
type AccountPublic = <Signature as Verify>::Signer;
|
||||
|
||||
const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
|
||||
|
||||
/// Node `ChainSpec` extensions.
|
||||
///
|
||||
/// Additional parameters for some Substrate core modules,
|
||||
/// customizable from the chain spec.
|
||||
#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Extensions {
|
||||
/// Block numbers with known hashes.
|
||||
pub fork_blocks: sc_client::ForkBlocks<Block>,
|
||||
/// Known bad block hashes.
|
||||
pub bad_blocks: sc_client::BadBlocks<Block>,
|
||||
}
|
||||
|
||||
/// Specialized `ChainSpec`.
|
||||
pub type ChainSpec = sc_service::ChainSpec<
|
||||
GenesisConfig,
|
||||
Extensions,
|
||||
>;
|
||||
/// Flaming Fir testnet generator
|
||||
pub fn flaming_fir_config() -> Result<ChainSpec, String> {
|
||||
ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..])
|
||||
}
|
||||
|
||||
fn session_keys(
|
||||
grandpa: GrandpaId,
|
||||
babe: BabeId,
|
||||
im_online: ImOnlineId,
|
||||
authority_discovery: AuthorityDiscoveryId,
|
||||
) -> SessionKeys {
|
||||
SessionKeys { grandpa, babe, im_online, authority_discovery }
|
||||
}
|
||||
|
||||
fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
// stash, controller, session-key
|
||||
// generated with secret:
|
||||
// for i in 1 2 3 4 ; do for j in stash controller; do subkey inspect "$secret"/fir/$j/$i; done; done
|
||||
// and
|
||||
// for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done
|
||||
|
||||
let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)> = vec![(
|
||||
// 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy
|
||||
hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(),
|
||||
// 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq
|
||||
hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(),
|
||||
// 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC
|
||||
hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(),
|
||||
// 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8
|
||||
hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(),
|
||||
// 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8
|
||||
hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(),
|
||||
// 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8
|
||||
hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(),
|
||||
),(
|
||||
// 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2
|
||||
hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(),
|
||||
// 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF
|
||||
hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(),
|
||||
// 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE
|
||||
hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(),
|
||||
// 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ
|
||||
hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(),
|
||||
// 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ
|
||||
hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(),
|
||||
// 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ
|
||||
hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(),
|
||||
),(
|
||||
// 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp
|
||||
hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(),
|
||||
// 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9
|
||||
hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(),
|
||||
// 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d
|
||||
hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(),
|
||||
// 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH
|
||||
hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(),
|
||||
// 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH
|
||||
hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(),
|
||||
// 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH
|
||||
hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(),
|
||||
),(
|
||||
// 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9
|
||||
hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(),
|
||||
// 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn
|
||||
hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(),
|
||||
// 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4
|
||||
hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(),
|
||||
// 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x
|
||||
hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(),
|
||||
// 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x
|
||||
hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(),
|
||||
// 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x
|
||||
hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(),
|
||||
)];
|
||||
|
||||
// generated with secret: subkey inspect "$secret"/fir
|
||||
let root_key: AccountId = hex![
|
||||
// 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo
|
||||
"9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"
|
||||
].into();
|
||||
|
||||
let endowed_accounts: Vec<AccountId> = vec![root_key.clone()];
|
||||
|
||||
testnet_genesis(
|
||||
initial_authorities,
|
||||
root_key,
|
||||
Some(endowed_accounts),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Staging testnet config.
|
||||
pub fn staging_testnet_config() -> ChainSpec {
|
||||
let boot_nodes = vec![];
|
||||
ChainSpec::from_genesis(
|
||||
"Staging Testnet",
|
||||
"staging_testnet",
|
||||
staging_testnet_config_genesis,
|
||||
boot_nodes,
|
||||
Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])),
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper function to generate a crypto pair from seed
|
||||
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
||||
TPublic::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
.public()
|
||||
}
|
||||
|
||||
/// Helper function to generate an account ID from seed
|
||||
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId where
|
||||
AccountPublic: From<<TPublic::Pair as Pair>::Public>
|
||||
{
|
||||
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
|
||||
}
|
||||
|
||||
/// Helper function to generate stash, controller and session key from seed
|
||||
pub fn get_authority_keys_from_seed(seed: &str) -> (
|
||||
AccountId,
|
||||
AccountId,
|
||||
GrandpaId,
|
||||
BabeId,
|
||||
ImOnlineId,
|
||||
AuthorityDiscoveryId,
|
||||
) {
|
||||
(
|
||||
get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
|
||||
get_account_id_from_seed::<sr25519::Public>(seed),
|
||||
get_from_seed::<GrandpaId>(seed),
|
||||
get_from_seed::<BabeId>(seed),
|
||||
get_from_seed::<ImOnlineId>(seed),
|
||||
get_from_seed::<AuthorityDiscoveryId>(seed),
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper function to create GenesisConfig for testing
|
||||
pub fn testnet_genesis(
|
||||
initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)>,
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Option<Vec<AccountId>>,
|
||||
enable_println: bool,
|
||||
) -> GenesisConfig {
|
||||
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(|| {
|
||||
vec![
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
||||
]
|
||||
});
|
||||
let num_endowed_accounts = endowed_accounts.len();
|
||||
|
||||
const ENDOWMENT: Balance = 10_000_000 * DOLLARS;
|
||||
const STASH: Balance = 100 * DOLLARS;
|
||||
|
||||
GenesisConfig {
|
||||
frame_system: Some(SystemConfig {
|
||||
code: WASM_BINARY.to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
pallet_balances: Some(BalancesConfig {
|
||||
balances: endowed_accounts.iter().cloned()
|
||||
.map(|k| (k, ENDOWMENT))
|
||||
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
||||
.collect(),
|
||||
vesting: vec![],
|
||||
}),
|
||||
pallet_indices: Some(IndicesConfig {
|
||||
ids: endowed_accounts.iter().cloned()
|
||||
.chain(initial_authorities.iter().map(|x| x.0.clone()))
|
||||
.collect::<Vec<_>>(),
|
||||
}),
|
||||
pallet_session: Some(SessionConfig {
|
||||
keys: initial_authorities.iter().map(|x| {
|
||||
(x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()))
|
||||
}).collect::<Vec<_>>(),
|
||||
}),
|
||||
pallet_staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
validator_count: initial_authorities.len() as u32 * 2,
|
||||
minimum_validator_count: initial_authorities.len() as u32,
|
||||
stakers: initial_authorities.iter().map(|x| {
|
||||
(x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)
|
||||
}).collect(),
|
||||
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
|
||||
slash_reward_fraction: Perbill::from_percent(10),
|
||||
.. Default::default()
|
||||
}),
|
||||
pallet_democracy: Some(DemocracyConfig::default()),
|
||||
pallet_collective_Instance1: Some(CouncilConfig {
|
||||
members: endowed_accounts.iter().cloned()
|
||||
.collect::<Vec<_>>()[..(num_endowed_accounts + 1) / 2].to_vec(),
|
||||
phantom: Default::default(),
|
||||
}),
|
||||
pallet_collective_Instance2: Some(TechnicalCommitteeConfig {
|
||||
members: endowed_accounts.iter().cloned()
|
||||
.collect::<Vec<_>>()[..(num_endowed_accounts + 1) / 2].to_vec(),
|
||||
phantom: Default::default(),
|
||||
}),
|
||||
pallet_contracts: Some(ContractsConfig {
|
||||
current_schedule: pallet_contracts::Schedule {
|
||||
enable_println, // this should only be enabled on development chains
|
||||
..Default::default()
|
||||
},
|
||||
gas_price: 1 * MILLICENTS,
|
||||
}),
|
||||
pallet_sudo: Some(SudoConfig {
|
||||
key: root_key,
|
||||
}),
|
||||
pallet_babe: Some(BabeConfig {
|
||||
authorities: vec![],
|
||||
}),
|
||||
pallet_im_online: Some(ImOnlineConfig {
|
||||
keys: vec![],
|
||||
}),
|
||||
pallet_authority_discovery: Some(AuthorityDiscoveryConfig {
|
||||
keys: vec![],
|
||||
}),
|
||||
pallet_grandpa: Some(GrandpaConfig {
|
||||
authorities: vec![],
|
||||
}),
|
||||
pallet_membership_Instance1: Some(Default::default()),
|
||||
pallet_treasury: Some(Default::default()),
|
||||
// here comes configuration for Kovan chain
|
||||
bridge_eth_poa: Some(BridgeEthPoaConfig {
|
||||
initial_header: sp_bridge_eth_poa::Header {
|
||||
parent_hash: Default::default(),
|
||||
timestamp: 0,
|
||||
number: 0,
|
||||
author: Default::default(),
|
||||
transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(),
|
||||
uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(),
|
||||
extra_data: vec![],
|
||||
state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(),
|
||||
receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(),
|
||||
log_bloom: Default::default(),
|
||||
gas_used: Default::default(),
|
||||
gas_limit: 6000000.into(),
|
||||
difficulty: 131072.into(),
|
||||
seal: vec![
|
||||
vec![128].into(),
|
||||
vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(),
|
||||
],
|
||||
},
|
||||
initial_difficulty: 0.into(),
|
||||
initial_validators: vec![
|
||||
[0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58,
|
||||
0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(),
|
||||
[0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d,
|
||||
0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(),
|
||||
[0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8,
|
||||
0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(),
|
||||
[0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60,
|
||||
0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(),
|
||||
[0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5,
|
||||
0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(),
|
||||
[0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9,
|
||||
0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(),
|
||||
[0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01,
|
||||
0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(),
|
||||
[0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C,
|
||||
0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(),
|
||||
[0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c,
|
||||
0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(),
|
||||
],
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn development_config_genesis() -> GenesisConfig {
|
||||
testnet_genesis(
|
||||
vec![
|
||||
get_authority_keys_from_seed("Alice"),
|
||||
],
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
None,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
/// Development config (single validator Alice)
|
||||
pub fn development_config() -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Development",
|
||||
"dev",
|
||||
development_config_genesis,
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn local_testnet_genesis() -> GenesisConfig {
|
||||
testnet_genesis(
|
||||
vec![
|
||||
get_authority_keys_from_seed("Alice"),
|
||||
get_authority_keys_from_seed("Bob"),
|
||||
],
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Local testnet config (multivalidator Alice + Bob)
|
||||
pub fn local_testnet_config() -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Local Testnet",
|
||||
"local_testnet",
|
||||
local_testnet_genesis,
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use crate::service::{new_full, new_light};
|
||||
use sc_service_test;
|
||||
|
||||
fn local_testnet_genesis_instant_single() -> GenesisConfig {
|
||||
testnet_genesis(
|
||||
vec![
|
||||
get_authority_keys_from_seed("Alice"),
|
||||
],
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Local testnet config (single validator - Alice)
|
||||
pub fn integration_test_config_with_single_authority() -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Integration Test",
|
||||
"test",
|
||||
local_testnet_genesis_instant_single,
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Local testnet config (multivalidator Alice + Bob)
|
||||
pub fn integration_test_config_with_two_authorities() -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Integration Test",
|
||||
"test",
|
||||
local_testnet_genesis,
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_connectivity() {
|
||||
sc_service_test::connectivity(
|
||||
integration_test_config_with_two_authorities(),
|
||||
|config| new_full(config),
|
||||
|config| new_light(config),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
[package]
|
||||
name = "node-runtime"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
# third-party dependencies
|
||||
codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] }
|
||||
integer-sqrt = { version = "0.1.2" }
|
||||
safe-mix = { version = "1.0", default-features = false }
|
||||
rustc-hex = { version = "2.0", optional = true }
|
||||
serde = { version = "1.0.102", optional = true }
|
||||
|
||||
# primitives
|
||||
sp-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../primitives/authority-discovery" }
|
||||
sp-consensus-babe = { version = "0.8", default-features = false, path = "../../../primitives/consensus/babe" }
|
||||
sp-block-builder = { path = "../../../primitives/block-builder", default-features = false}
|
||||
sp-inherents = { version = "2.0.0", default-features = false, path = "../../../primitives/inherents" }
|
||||
node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" }
|
||||
sp-offchain = { version = "2.0.0", default-features = false, path = "../../../primitives/offchain" }
|
||||
sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" }
|
||||
sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" }
|
||||
sp-api = { version = "2.0.0", default-features = false, path = "../../../primitives/api" }
|
||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" }
|
||||
sp-staking = { version = "2.0.0", default-features = false, path = "../../../primitives/staking" }
|
||||
sp-keyring = { version = "2.0.0", optional = true, path = "../../../primitives/keyring" }
|
||||
sp-session = { version = "2.0.0", default-features = false, path = "../../../primitives/session" }
|
||||
sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../../primitives/transaction-pool" }
|
||||
sp-version = { version = "2.0.0", default-features = false, path = "../../../primitives/version" }
|
||||
sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa", default-features = false }
|
||||
|
||||
# frame dependencies
|
||||
frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" }
|
||||
frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" }
|
||||
frame-system = { version = "2.0.0", default-features = false, path = "../../../frame/system" }
|
||||
frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/system/rpc/runtime-api/" }
|
||||
pallet-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../frame/authority-discovery" }
|
||||
pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" }
|
||||
pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" }
|
||||
pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" }
|
||||
pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" }
|
||||
pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" }
|
||||
pallet-contracts-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" }
|
||||
pallet-democracy = { version = "2.0.0", default-features = false, path = "../../../frame/democracy" }
|
||||
pallet-elections-phragmen = { version = "2.0.0", default-features = false, path = "../../../frame/elections-phragmen" }
|
||||
pallet-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../frame/finality-tracker" }
|
||||
pallet-grandpa = { version = "2.0.0", default-features = false, path = "../../../frame/grandpa" }
|
||||
pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" }
|
||||
pallet-indices = { version = "2.0.0", default-features = false, path = "../../../frame/indices" }
|
||||
pallet-membership = { version = "2.0.0", default-features = false, path = "../../../frame/membership" }
|
||||
pallet-nicks = { version = "2.0.0", default-features = false, path = "../../../frame/nicks" }
|
||||
pallet-offences = { version = "2.0.0", default-features = false, path = "../../../frame/offences" }
|
||||
pallet-randomness-collective-flip = { version = "2.0.0", default-features = false, path = "../../../frame/randomness-collective-flip" }
|
||||
pallet-session = { version = "2.0.0", features = ["historical"], path = "../../../frame/session", default-features = false }
|
||||
pallet-staking = { version = "2.0.0", features = ["migrate"], path = "../../../frame/staking", default-features = false }
|
||||
pallet-staking-reward-curve = { version = "2.0.0", path = "../../../frame/staking/reward-curve" }
|
||||
pallet-sudo = { version = "2.0.0", default-features = false, path = "../../../frame/sudo" }
|
||||
pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" }
|
||||
pallet-treasury = { version = "2.0.0", default-features = false, path = "../../../frame/treasury" }
|
||||
pallet-utility = { version = "2.0.0", default-features = false, path = "../../../frame/utility" }
|
||||
pallet-transaction-payment = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment" }
|
||||
pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" }
|
||||
# TODO: Update this
|
||||
bridge-eth-poa = { package = "pallet-bridge-eth-poa", path = "../../../frame/bridge-eth-poa", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" }
|
||||
|
||||
[dev-dependencies]
|
||||
sp-io = { version = "2.0.0", path = "../../../primitives/io" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"sp-authority-discovery/std",
|
||||
"pallet-authority-discovery/std",
|
||||
"pallet-authorship/std",
|
||||
"sp-consensus-babe/std",
|
||||
"pallet-babe/std",
|
||||
"pallet-balances/std",
|
||||
"sp-block-builder/std",
|
||||
"sp-bridge-eth-poa/std",
|
||||
"bridge-eth-poa/std", # TODO: Update this
|
||||
"codec/std",
|
||||
"pallet-collective/std",
|
||||
"pallet-contracts-rpc-runtime-api/std",
|
||||
"pallet-contracts/std",
|
||||
"pallet-democracy/std",
|
||||
"pallet-elections-phragmen/std",
|
||||
"frame-executive/std",
|
||||
"pallet-finality-tracker/std",
|
||||
"pallet-grandpa/std",
|
||||
"pallet-im-online/std",
|
||||
"pallet-indices/std",
|
||||
"sp-inherents/std",
|
||||
"pallet-membership/std",
|
||||
"pallet-nicks/std",
|
||||
"node-primitives/std",
|
||||
"sp-offchain/std",
|
||||
"pallet-offences/std",
|
||||
"sp-core/std",
|
||||
"pallet-randomness-collective-flip/std",
|
||||
"sp-std/std",
|
||||
"rustc-hex",
|
||||
"safe-mix/std",
|
||||
"serde",
|
||||
"pallet-session/std",
|
||||
"sp-api/std",
|
||||
"sp-runtime/std",
|
||||
"sp-staking/std",
|
||||
"pallet-staking/std",
|
||||
"sp-keyring",
|
||||
"sp-session/std",
|
||||
"pallet-sudo/std",
|
||||
"frame-support/std",
|
||||
"frame-system-rpc-runtime-api/std",
|
||||
"frame-system/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-transaction-payment-rpc-runtime-api/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"pallet-treasury/std",
|
||||
"sp-transaction-pool/std",
|
||||
"pallet-utility/std",
|
||||
"sp-version/std",
|
||||
]
|
||||
@@ -0,0 +1,836 @@
|
||||
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm.
|
||||
|
||||
#![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"]
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types, debug,
|
||||
weights::Weight,
|
||||
traits::{SplitTwoWays, Currency, Randomness},
|
||||
};
|
||||
use sp_core::u32_trait::{_1, _2, _3, _4};
|
||||
use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature};
|
||||
use sp_api::impl_runtime_apis;
|
||||
use sp_runtime::{
|
||||
Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str
|
||||
};
|
||||
use sp_runtime::curve::PiecewiseLinear;
|
||||
use sp_runtime::transaction_validity::TransactionValidity;
|
||||
use sp_runtime::traits::{
|
||||
self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion,
|
||||
OpaqueKeys,
|
||||
};
|
||||
use sp_version::RuntimeVersion;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use sp_version::NativeVersion;
|
||||
use sp_core::OpaqueMetadata;
|
||||
use pallet_grandpa::AuthorityList as GrandpaAuthorityList;
|
||||
use pallet_grandpa::fg_primitives;
|
||||
use pallet_im_online::sr25519::{AuthorityId as ImOnlineId};
|
||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
|
||||
use pallet_contracts_rpc_runtime_api::ContractExecResult;
|
||||
use frame_system::offchain::TransactionSubmitter;
|
||||
use sp_inherents::{InherentData, CheckInherentsResult};
|
||||
|
||||
#[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 pallet_contracts::Gas;
|
||||
pub use frame_support::StorageValue;
|
||||
pub use pallet_staking::StakerStatus;
|
||||
pub use bridge_eth_poa::Call as BridgeEthPoaCall; // TODO: Update name
|
||||
|
||||
/// Implementations of some helper traits passed into runtime modules as associated types.
|
||||
pub mod impls;
|
||||
use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment};
|
||||
|
||||
/// Constant values used within the runtime.
|
||||
pub mod constants;
|
||||
use constants::{time::*, currency::*};
|
||||
|
||||
// Make the WASM binary available.
|
||||
#[cfg(feature = "std")]
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
/// Runtime version.
|
||||
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("node"),
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
// Per convention: if the runtime behavior changes, increment spec_version
|
||||
// and set impl_version to equal spec_version. If only runtime
|
||||
// implementation changes and behavior does not, then leave spec_version as
|
||||
// is and increment impl_version.
|
||||
spec_version: 202,
|
||||
impl_version: 202,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
/// Native version.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub fn native_version() -> NativeVersion {
|
||||
NativeVersion {
|
||||
runtime_version: VERSION,
|
||||
can_author_with: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
|
||||
|
||||
pub type DealWithFees = SplitTwoWays<
|
||||
Balance,
|
||||
NegativeImbalance,
|
||||
_4, Treasury, // 4 parts (80%) goes to the treasury.
|
||||
_1, Author, // 1 part (20%) goes to the block author.
|
||||
>;
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: BlockNumber = 250;
|
||||
pub const MaximumBlockWeight: Weight = 1_000_000_000;
|
||||
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
|
||||
pub const Version: RuntimeVersion = VERSION;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
||||
}
|
||||
|
||||
impl frame_system::Trait for Runtime {
|
||||
type Origin = Origin;
|
||||
type Call = Call;
|
||||
type Index = Index;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = Indices;
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
type Event = Event;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type MaximumBlockWeight = MaximumBlockWeight;
|
||||
type MaximumBlockLength = MaximumBlockLength;
|
||||
type AvailableBlockRatio = AvailableBlockRatio;
|
||||
type Version = Version;
|
||||
type ModuleToIndex = ModuleToIndex;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
// One storage item; value is size 4+4+16+32 bytes = 56 bytes.
|
||||
pub const MultisigDepositBase: Balance = 30 * CENTS;
|
||||
// Additional storage item size of 32 bytes.
|
||||
pub const MultisigDepositFactor: Balance = 5 * CENTS;
|
||||
pub const MaxSignatories: u16 = 100;
|
||||
}
|
||||
|
||||
impl pallet_utility::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Call = Call;
|
||||
type Currency = Balances;
|
||||
type MultisigDepositBase = MultisigDepositBase;
|
||||
type MultisigDepositFactor = MultisigDepositFactor;
|
||||
type MaxSignatories = MaxSignatories;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
|
||||
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
|
||||
}
|
||||
|
||||
impl pallet_babe::Trait for Runtime {
|
||||
type EpochDuration = EpochDuration;
|
||||
type ExpectedBlockTime = ExpectedBlockTime;
|
||||
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
||||
}
|
||||
|
||||
impl pallet_indices::Trait for Runtime {
|
||||
type AccountIndex = AccountIndex;
|
||||
type IsDeadAccount = Balances;
|
||||
type ResolveHint = pallet_indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
|
||||
pub const TransferFee: Balance = 1 * CENTS;
|
||||
pub const CreationFee: Balance = 1 * CENTS;
|
||||
}
|
||||
|
||||
impl pallet_balances::Trait for Runtime {
|
||||
type Balance = Balance;
|
||||
type OnFreeBalanceZero = ((Staking, Contracts), Session);
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = Indices;
|
||||
type Event = Event;
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const TransactionBaseFee: Balance = 1 * CENTS;
|
||||
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
|
||||
// setting this to zero will disable the weight fee.
|
||||
pub const WeightFeeCoefficient: Balance = 1_000;
|
||||
// for a sane configuration, this should always be less than `AvailableBlockRatio`.
|
||||
pub const TargetBlockFullness: Perbill = Perbill::from_percent(25);
|
||||
}
|
||||
|
||||
impl pallet_transaction_payment::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type OnTransactionPayment = DealWithFees;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
type WeightToFee = LinearWeightToFee<WeightFeeCoefficient>;
|
||||
type FeeMultiplierUpdate = TargetedFeeAdjustment<TargetBlockFullness>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const MinimumPeriod: Moment = SLOT_DURATION / 2;
|
||||
}
|
||||
impl pallet_timestamp::Trait for Runtime {
|
||||
type Moment = Moment;
|
||||
type OnTimestampSet = Babe;
|
||||
type MinimumPeriod = MinimumPeriod;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const UncleGenerations: BlockNumber = 5;
|
||||
}
|
||||
|
||||
impl pallet_authorship::Trait for Runtime {
|
||||
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
|
||||
type UncleGenerations = UncleGenerations;
|
||||
type FilterUncle = ();
|
||||
type EventHandler = (Staking, ImOnline);
|
||||
}
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {
|
||||
pub grandpa: Grandpa,
|
||||
pub babe: Babe,
|
||||
pub im_online: ImOnline,
|
||||
pub authority_discovery: AuthorityDiscovery,
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
|
||||
}
|
||||
|
||||
impl pallet_session::Trait for Runtime {
|
||||
type OnSessionEnding = Staking;
|
||||
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
||||
type ShouldEndSession = Babe;
|
||||
type Event = Event;
|
||||
type Keys = SessionKeys;
|
||||
type ValidatorId = <Self as frame_system::Trait>::AccountId;
|
||||
type ValidatorIdOf = pallet_staking::StashOf<Self>;
|
||||
type SelectInitialValidators = Staking;
|
||||
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
|
||||
}
|
||||
|
||||
impl pallet_session::historical::Trait for Runtime {
|
||||
type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
|
||||
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
|
||||
}
|
||||
|
||||
pallet_staking_reward_curve::build! {
|
||||
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
|
||||
min_inflation: 0_025_000,
|
||||
max_inflation: 0_100_000,
|
||||
ideal_stake: 0_500_000,
|
||||
falloff: 0_050_000,
|
||||
max_piece_count: 40,
|
||||
test_precision: 0_005_000,
|
||||
);
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const SessionsPerEra: sp_staking::SessionIndex = 6;
|
||||
pub const BondingDuration: pallet_staking::EraIndex = 24 * 28;
|
||||
pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration.
|
||||
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
|
||||
}
|
||||
|
||||
impl pallet_staking::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type Time = Timestamp;
|
||||
type CurrencyToVote = CurrencyToVoteHandler;
|
||||
type RewardRemainder = Treasury;
|
||||
type Event = Event;
|
||||
type Slash = Treasury; // send the slashed funds to the treasury.
|
||||
type Reward = (); // rewards are minted from the void
|
||||
type SessionsPerEra = SessionsPerEra;
|
||||
type BondingDuration = BondingDuration;
|
||||
type SlashDeferDuration = SlashDeferDuration;
|
||||
/// A super-majority of the council can cancel the slash.
|
||||
type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>;
|
||||
type SessionInterface = Self;
|
||||
type RewardCurve = RewardCurve;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES;
|
||||
pub const MinimumDeposit: Balance = 100 * DOLLARS;
|
||||
pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
|
||||
pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
// One cent: $10,000 / MB
|
||||
pub const PreimageByteDeposit: Balance = 1 * CENTS;
|
||||
}
|
||||
|
||||
impl pallet_democracy::Trait for Runtime {
|
||||
type Proposal = Call;
|
||||
type Event = Event;
|
||||
type Currency = Balances;
|
||||
type EnactmentPeriod = EnactmentPeriod;
|
||||
type LaunchPeriod = LaunchPeriod;
|
||||
type VotingPeriod = VotingPeriod;
|
||||
type EmergencyVotingPeriod = EmergencyVotingPeriod;
|
||||
type MinimumDeposit = MinimumDeposit;
|
||||
/// A straight majority of the council can decide what their next motion is.
|
||||
type ExternalOrigin = pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
|
||||
/// A super-majority can have the next scheduled referendum be a straight majority-carries vote.
|
||||
type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>;
|
||||
/// A unanimous council can have the next scheduled referendum be a straight default-carries
|
||||
/// (NTB) vote.
|
||||
type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>;
|
||||
/// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
|
||||
/// be tabled immediately and with a shorter voting/enactment period.
|
||||
type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>;
|
||||
// To cancel a proposal which has been passed, 2/3 of the council must agree to it.
|
||||
type CancellationOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>;
|
||||
// Any single technical committee member may veto a coming council proposal, however they can
|
||||
// only do it once and it lasts only for the cooloff period.
|
||||
type VetoOrigin = pallet_collective::EnsureMember<AccountId, TechnicalCollective>;
|
||||
type CooloffPeriod = CooloffPeriod;
|
||||
type PreimageByteDeposit = PreimageByteDeposit;
|
||||
type Slash = Treasury;
|
||||
}
|
||||
|
||||
type CouncilCollective = pallet_collective::Instance1;
|
||||
impl pallet_collective::Trait<CouncilCollective> for Runtime {
|
||||
type Origin = Origin;
|
||||
type Proposal = Call;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const CandidacyBond: Balance = 10 * DOLLARS;
|
||||
pub const VotingBond: Balance = 1 * DOLLARS;
|
||||
pub const TermDuration: BlockNumber = 7 * DAYS;
|
||||
pub const DesiredMembers: u32 = 13;
|
||||
pub const DesiredRunnersUp: u32 = 7;
|
||||
}
|
||||
|
||||
impl pallet_elections_phragmen::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Currency = Balances;
|
||||
type CurrencyToVote = CurrencyToVoteHandler;
|
||||
type CandidacyBond = CandidacyBond;
|
||||
type VotingBond = VotingBond;
|
||||
type TermDuration = TermDuration;
|
||||
type DesiredMembers = DesiredMembers;
|
||||
type DesiredRunnersUp = DesiredRunnersUp;
|
||||
type LoserCandidate = ();
|
||||
type BadReport = ();
|
||||
type KickedMember = ();
|
||||
type ChangeMembers = Council;
|
||||
}
|
||||
|
||||
type TechnicalCollective = pallet_collective::Instance2;
|
||||
impl pallet_collective::Trait<TechnicalCollective> for Runtime {
|
||||
type Origin = Origin;
|
||||
type Proposal = Call;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl pallet_membership::Trait<pallet_membership::Instance1> for Runtime {
|
||||
type Event = Event;
|
||||
type AddOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
|
||||
type RemoveOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
|
||||
type SwapOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
|
||||
type ResetOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
|
||||
type MembershipInitialized = TechnicalCommittee;
|
||||
type MembershipChanged = TechnicalCommittee;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ProposalBond: Permill = Permill::from_percent(5);
|
||||
pub const ProposalBondMinimum: Balance = 1 * DOLLARS;
|
||||
pub const SpendPeriod: BlockNumber = 1 * DAYS;
|
||||
pub const Burn: Permill = Permill::from_percent(50);
|
||||
pub const TipCountdown: BlockNumber = 1 * DAYS;
|
||||
pub const TipFindersFee: Percent = Percent::from_percent(20);
|
||||
pub const TipReportDepositBase: Balance = 1 * DOLLARS;
|
||||
pub const TipReportDepositPerByte: Balance = 1 * CENTS;
|
||||
}
|
||||
|
||||
impl pallet_treasury::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>;
|
||||
type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>;
|
||||
type Event = Event;
|
||||
type ProposalRejection = ();
|
||||
type ProposalBond = ProposalBond;
|
||||
type ProposalBondMinimum = ProposalBondMinimum;
|
||||
type SpendPeriod = SpendPeriod;
|
||||
type Burn = Burn;
|
||||
type Tippers = Elections;
|
||||
type TipCountdown = TipCountdown;
|
||||
type TipFindersFee = TipFindersFee;
|
||||
type TipReportDepositBase = TipReportDepositBase;
|
||||
type TipReportDepositPerByte = TipReportDepositPerByte;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ContractTransferFee: Balance = 1 * CENTS;
|
||||
pub const ContractCreationFee: Balance = 1 * CENTS;
|
||||
pub const ContractTransactionBaseFee: Balance = 1 * CENTS;
|
||||
pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS;
|
||||
pub const ContractFee: Balance = 1 * CENTS;
|
||||
pub const TombstoneDeposit: Balance = 1 * DOLLARS;
|
||||
pub const RentByteFee: Balance = 1 * DOLLARS;
|
||||
pub const RentDepositOffset: Balance = 1000 * DOLLARS;
|
||||
pub const SurchargeReward: Balance = 150 * DOLLARS;
|
||||
}
|
||||
|
||||
impl pallet_contracts::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type Time = Timestamp;
|
||||
type Randomness = RandomnessCollectiveFlip;
|
||||
type Call = Call;
|
||||
type Event = Event;
|
||||
type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminator<Runtime>;
|
||||
type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor<Runtime>;
|
||||
type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter<Runtime>;
|
||||
type GasPayment = ();
|
||||
type RentPayment = ();
|
||||
type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;
|
||||
type TombstoneDeposit = TombstoneDeposit;
|
||||
type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;
|
||||
type RentByteFee = RentByteFee;
|
||||
type RentDepositOffset = RentDepositOffset;
|
||||
type SurchargeReward = SurchargeReward;
|
||||
type TransferFee = ContractTransferFee;
|
||||
type CreationFee = ContractCreationFee;
|
||||
type TransactionBaseFee = ContractTransactionBaseFee;
|
||||
type TransactionByteFee = ContractTransactionByteFee;
|
||||
type ContractFee = ContractFee;
|
||||
type CallBaseFee = pallet_contracts::DefaultCallBaseFee;
|
||||
type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee;
|
||||
type MaxDepth = pallet_contracts::DefaultMaxDepth;
|
||||
type MaxValueSize = pallet_contracts::DefaultMaxValueSize;
|
||||
type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit;
|
||||
}
|
||||
|
||||
impl pallet_sudo::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Proposal = Call;
|
||||
}
|
||||
|
||||
/// A runtime transaction submitter.
|
||||
pub type SubmitTransaction = TransactionSubmitter<ImOnlineId, Runtime, UncheckedExtrinsic>;
|
||||
|
||||
parameter_types! {
|
||||
pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _;
|
||||
}
|
||||
|
||||
impl pallet_im_online::Trait for Runtime {
|
||||
type AuthorityId = ImOnlineId;
|
||||
type Call = Call;
|
||||
type Event = Event;
|
||||
type SubmitTransaction = SubmitTransaction;
|
||||
type ReportUnresponsiveness = Offences;
|
||||
type SessionDuration = SessionDuration;
|
||||
}
|
||||
|
||||
impl pallet_offences::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
|
||||
type OnOffenceHandler = Staking;
|
||||
}
|
||||
|
||||
impl pallet_authority_discovery::Trait for Runtime {}
|
||||
|
||||
impl pallet_grandpa::Trait for Runtime {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const WindowSize: BlockNumber = 101;
|
||||
pub const ReportLatency: BlockNumber = 1000;
|
||||
}
|
||||
|
||||
impl pallet_finality_tracker::Trait for Runtime {
|
||||
type OnFinalizationStalled = Grandpa;
|
||||
type WindowSize = WindowSize;
|
||||
type ReportLatency = ReportLatency;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ReservationFee: Balance = 1 * DOLLARS;
|
||||
pub const MinLength: usize = 3;
|
||||
pub const MaxLength: usize = 16;
|
||||
}
|
||||
|
||||
impl pallet_nicks::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Currency = Balances;
|
||||
type ReservationFee = ReservationFee;
|
||||
type Slashed = Treasury;
|
||||
type ForceOrigin = pallet_collective::EnsureMember<AccountId, CouncilCollective>;
|
||||
type MinLength = MinLength;
|
||||
type MaxLength = MaxLength;
|
||||
}
|
||||
|
||||
impl frame_system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
|
||||
type Public = <Signature as traits::Verify>::Signer;
|
||||
type Signature = Signature;
|
||||
|
||||
fn create_transaction<TSigner: frame_system::offchain::Signer<Self::Public, Self::Signature>>(
|
||||
call: Call,
|
||||
public: Self::Public,
|
||||
account: AccountId,
|
||||
index: Index,
|
||||
) -> Option<(Call, <UncheckedExtrinsic as traits::Extrinsic>::SignaturePayload)> {
|
||||
// take the biggest period possible.
|
||||
let period = BlockHashCount::get()
|
||||
.checked_next_power_of_two()
|
||||
.map(|c| c / 2)
|
||||
.unwrap_or(2) as u64;
|
||||
let current_block = System::block_number()
|
||||
.saturated_into::<u64>()
|
||||
// The `System::block_number` is initialized with `n+1`,
|
||||
// so the actual block number is `n`.
|
||||
.saturating_sub(1);
|
||||
let tip = 0;
|
||||
let extra: SignedExtra = (
|
||||
frame_system::CheckVersion::<Runtime>::new(),
|
||||
frame_system::CheckGenesis::<Runtime>::new(),
|
||||
frame_system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
|
||||
frame_system::CheckNonce::<Runtime>::from(index),
|
||||
frame_system::CheckWeight::<Runtime>::new(),
|
||||
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
|
||||
Default::default(),
|
||||
);
|
||||
let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
|
||||
debug::warn!("Unable to create signed payload: {:?}", e);
|
||||
}).ok()?;
|
||||
let signature = TSigner::sign(public, &raw_payload)?;
|
||||
let address = Indices::unlookup(account);
|
||||
let (call, extra, _) = raw_payload.deconstruct();
|
||||
Some((call, (address, signature, extra)))
|
||||
}
|
||||
}
|
||||
|
||||
impl bridge_eth_poa::Trait for Runtime {
|
||||
type OnHeadersSubmitted = ();
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = node_primitives::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: frame_system::{Module, Call, Storage, Config, Event},
|
||||
Utility: pallet_utility::{Module, Call, Storage, Event<T>},
|
||||
Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
|
||||
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
|
||||
Authorship: pallet_authorship::{Module, Call, Storage, Inherent},
|
||||
Indices: pallet_indices,
|
||||
Balances: pallet_balances,
|
||||
TransactionPayment: pallet_transaction_payment::{Module, Storage},
|
||||
Staking: pallet_staking,
|
||||
Session: pallet_session::{Module, Call, Storage, Event, Config<T>},
|
||||
Democracy: pallet_democracy::{Module, Call, Storage, Config, Event<T>},
|
||||
Council: pallet_collective::<Instance1>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
|
||||
TechnicalCommittee: pallet_collective::<Instance2>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
|
||||
Elections: pallet_elections_phragmen::{Module, Call, Storage, Event<T>},
|
||||
TechnicalMembership: pallet_membership::<Instance1>::{Module, Call, Storage, Event<T>, Config<T>},
|
||||
FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent},
|
||||
Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},
|
||||
Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},
|
||||
Contracts: pallet_contracts,
|
||||
Sudo: pallet_sudo,
|
||||
ImOnline: pallet_im_online::{Module, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
|
||||
AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config},
|
||||
Offences: pallet_offences::{Module, Call, Storage, Event},
|
||||
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
|
||||
Nicks: pallet_nicks::{Module, Call, Storage, Event<T>},
|
||||
BridgeEthPoa: bridge_eth_poa::{Module, Call, Config}, // TODO: Update this
|
||||
}
|
||||
);
|
||||
|
||||
/// The address format for describing accounts.
|
||||
pub type Address = <Indices as StaticLookup>::Source;
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// A Block signed with a Justification
|
||||
pub type SignedBlock = generic::SignedBlock<Block>;
|
||||
/// BlockId type as expected by this runtime.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
/// The SignedExtension to the basic transaction logic.
|
||||
pub type SignedExtra = (
|
||||
frame_system::CheckVersion<Runtime>,
|
||||
frame_system::CheckGenesis<Runtime>,
|
||||
frame_system::CheckEra<Runtime>,
|
||||
frame_system::CheckNonce<Runtime>,
|
||||
frame_system::CheckWeight<Runtime>,
|
||||
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||||
pallet_contracts::CheckBlockGasLimit<Runtime>,
|
||||
);
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
|
||||
/// The payload being signed in transactions.
|
||||
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
|
||||
/// Extrinsic type that has already been checked.
|
||||
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
|
||||
/// Executive: handles dispatch to the various modules.
|
||||
pub type Executive = frame_executive::Executive<Runtime, Block, frame_system::ChainContext<Runtime>, Runtime, AllModules>;
|
||||
|
||||
impl_runtime_apis! {
|
||||
impl sp_api::Core<Block> for Runtime {
|
||||
fn version() -> RuntimeVersion {
|
||||
VERSION
|
||||
}
|
||||
|
||||
fn execute_block(block: Block) {
|
||||
Executive::execute_block(block)
|
||||
}
|
||||
|
||||
fn initialize_block(header: &<Block as BlockT>::Header) {
|
||||
Executive::initialize_block(header)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_api::Metadata<Block> for Runtime {
|
||||
fn metadata() -> OpaqueMetadata {
|
||||
Runtime::metadata().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_block_builder::BlockBuilder<Block> for Runtime {
|
||||
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
|
||||
Executive::apply_extrinsic(extrinsic)
|
||||
}
|
||||
|
||||
fn finalize_block() -> <Block as BlockT>::Header {
|
||||
Executive::finalize_block()
|
||||
}
|
||||
|
||||
fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
|
||||
data.create_extrinsics()
|
||||
}
|
||||
|
||||
fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
|
||||
data.check_extrinsics(&block)
|
||||
}
|
||||
|
||||
fn random_seed() -> <Block as BlockT>::Hash {
|
||||
RandomnessCollectiveFlip::random_seed()
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
||||
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
|
||||
Executive::validate_transaction(tx)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
|
||||
fn offchain_worker(header: &<Block as BlockT>::Header) {
|
||||
Executive::offchain_worker(header)
|
||||
}
|
||||
}
|
||||
|
||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||
fn grandpa_authorities() -> GrandpaAuthorityList {
|
||||
Grandpa::grandpa_authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_consensus_babe::BabeApi<Block> for Runtime {
|
||||
fn configuration() -> sp_consensus_babe::BabeConfiguration {
|
||||
// The choice of `c` parameter (where `1 - c` represents the
|
||||
// probability of a slot being empty), is done in accordance to the
|
||||
// slot duration and expected target block time, for safely
|
||||
// resisting network delays of maximum two seconds.
|
||||
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
|
||||
sp_consensus_babe::BabeConfiguration {
|
||||
slot_duration: Babe::slot_duration(),
|
||||
epoch_length: EpochDuration::get(),
|
||||
c: PRIMARY_PROBABILITY,
|
||||
genesis_authorities: Babe::authorities(),
|
||||
randomness: Babe::randomness(),
|
||||
secondary_slots: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityDiscoveryId> {
|
||||
AuthorityDiscovery::authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
|
||||
fn account_nonce(account: AccountId) -> Index {
|
||||
System::account_nonce(account)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance> for Runtime {
|
||||
fn call(
|
||||
origin: AccountId,
|
||||
dest: AccountId,
|
||||
value: Balance,
|
||||
gas_limit: u64,
|
||||
input_data: Vec<u8>,
|
||||
) -> ContractExecResult {
|
||||
let exec_result = Contracts::bare_call(
|
||||
origin,
|
||||
dest.into(),
|
||||
value,
|
||||
gas_limit,
|
||||
input_data,
|
||||
);
|
||||
match exec_result {
|
||||
Ok(v) => ContractExecResult::Success {
|
||||
status: v.status,
|
||||
data: v.data,
|
||||
},
|
||||
Err(_) => ContractExecResult::Error,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_storage(
|
||||
address: AccountId,
|
||||
key: [u8; 32],
|
||||
) -> pallet_contracts_rpc_runtime_api::GetStorageResult {
|
||||
Contracts::get_storage(address, key).map_err(|rpc_err| {
|
||||
use pallet_contracts::GetStorageError;
|
||||
use pallet_contracts_rpc_runtime_api::{GetStorageError as RpcGetStorageError};
|
||||
/// Map the contract error into the RPC layer error.
|
||||
match rpc_err {
|
||||
GetStorageError::ContractDoesntExist => RpcGetStorageError::ContractDoesntExist,
|
||||
GetStorageError::IsTombstone => RpcGetStorageError::IsTombstone,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
|
||||
Block,
|
||||
Balance,
|
||||
UncheckedExtrinsic,
|
||||
> for Runtime {
|
||||
fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
|
||||
TransactionPayment::query_info(uxt, len)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_session::SessionKeys<Block> for Runtime {
|
||||
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
||||
SessionKeys::generate(seed)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_bridge_eth_poa::EthereumHeadersApi<Block> for Runtime {
|
||||
fn best_block() -> (u64, sp_bridge_eth_poa::H256) {
|
||||
BridgeEthPoa::best_block()
|
||||
}
|
||||
|
||||
fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool {
|
||||
BridgeEthPoa::is_import_requires_receipts(header)
|
||||
}
|
||||
|
||||
fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool {
|
||||
BridgeEthPoa::is_known_block(hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use frame_system::offchain::{SignAndSubmitTransaction, SubmitSignedTransaction};
|
||||
|
||||
#[test]
|
||||
fn validate_transaction_submitter_bounds() {
|
||||
fn is_submit_signed_transaction<T>() where
|
||||
T: SubmitSignedTransaction<
|
||||
Runtime,
|
||||
Call,
|
||||
>,
|
||||
{}
|
||||
|
||||
fn is_sign_and_submit_transaction<T>() where
|
||||
T: SignAndSubmitTransaction<
|
||||
Runtime,
|
||||
Call,
|
||||
Extrinsic=UncheckedExtrinsic,
|
||||
CreateTransaction=Runtime,
|
||||
Signer=ImOnlineId,
|
||||
>,
|
||||
{}
|
||||
|
||||
is_submit_signed_transaction::<SubmitTransaction>();
|
||||
is_sign_and_submit_transaction::<SubmitTransaction>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_hooks_weight_should_not_exceed_limits() {
|
||||
use frame_support::weights::WeighBlock;
|
||||
let check_for_block = |b| {
|
||||
let block_hooks_weight =
|
||||
<AllModules as WeighBlock<BlockNumber>>::on_initialize(b) +
|
||||
<AllModules as WeighBlock<BlockNumber>>::on_finalize(b);
|
||||
|
||||
assert_eq!(
|
||||
block_hooks_weight,
|
||||
0,
|
||||
"This test might fail simply because the value being compared to has increased to a \
|
||||
module declaring a new weight for a hook or call. In this case update the test and \
|
||||
happily move on.",
|
||||
);
|
||||
|
||||
// Invariant. Always must be like this to have a sane chain.
|
||||
assert!(block_hooks_weight < MaximumBlockWeight::get());
|
||||
|
||||
// Warning.
|
||||
if block_hooks_weight > MaximumBlockWeight::get() / 2 {
|
||||
println!(
|
||||
"block hooks weight is consuming more than a block's capacity. You probably want \
|
||||
to re-think this. This test will fail now."
|
||||
);
|
||||
assert!(false);
|
||||
}
|
||||
};
|
||||
|
||||
let _ = (0..100_000).for_each(check_for_block);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "node-testing"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Test utilities for Substrate node."
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
pallet-balances = { version = "2.0.0", path = "../../../frame/balances" }
|
||||
sc-client = { version = "2.0.0", path = "../../../client/" }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0" }
|
||||
pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" }
|
||||
pallet-grandpa = { version = "2.0.0", path = "../../../frame/grandpa" }
|
||||
pallet-indices = { version = "2.0.0", path = "../../../frame/indices" }
|
||||
sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" }
|
||||
node-executor = { version = "2.0.0", path = "../executor" }
|
||||
node-primitives = { version = "2.0.0", path = "../primitives" }
|
||||
node-runtime = { version = "2.0.0", path = "../runtime" }
|
||||
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
|
||||
sp-io = { version = "2.0.0", path = "../../../primitives/io" }
|
||||
frame-support = { version = "2.0.0", path = "../../../frame/support" }
|
||||
pallet-session = { version = "2.0.0", path = "../../../frame/session" }
|
||||
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
|
||||
pallet-staking = { version = "2.0.0", path = "../../../frame/staking" }
|
||||
sc-executor = { version = "2.0.0", path = "../../../client/executor" }
|
||||
frame-system = { version = "2.0.0", path = "../../../frame/system" }
|
||||
substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" }
|
||||
pallet-timestamp = { version = "2.0.0", path = "../../../frame/timestamp" }
|
||||
pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" }
|
||||
pallet-treasury = { version = "2.0.0", path = "../../../frame/treasury" }
|
||||
wabt = "0.9.2"
|
||||
sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" }
|
||||
@@ -0,0 +1,144 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Genesis Configuration.
|
||||
|
||||
use crate::keyring::*;
|
||||
use sp_keyring::{Ed25519Keyring, Sr25519Keyring};
|
||||
use node_runtime::{
|
||||
GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig,
|
||||
GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, BridgeEthPoaConfig,
|
||||
};
|
||||
use node_runtime::constants::currency::*;
|
||||
use sp_core::ChangesTrieConfiguration;
|
||||
use sp_runtime::Perbill;
|
||||
|
||||
|
||||
/// Create genesis runtime configuration for tests.
|
||||
pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig {
|
||||
GenesisConfig {
|
||||
frame_system: Some(SystemConfig {
|
||||
changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration {
|
||||
digest_interval: 2,
|
||||
digest_levels: 2,
|
||||
}) } else { None },
|
||||
code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()),
|
||||
}),
|
||||
pallet_indices: Some(IndicesConfig {
|
||||
ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()],
|
||||
}),
|
||||
pallet_balances: Some(BalancesConfig {
|
||||
balances: vec![
|
||||
(alice(), 111 * DOLLARS),
|
||||
(bob(), 100 * DOLLARS),
|
||||
(charlie(), 100_000_000 * DOLLARS),
|
||||
(dave(), 111 * DOLLARS),
|
||||
(eve(), 101 * DOLLARS),
|
||||
(ferdie(), 100 * DOLLARS),
|
||||
],
|
||||
vesting: vec![],
|
||||
}),
|
||||
pallet_session: Some(SessionConfig {
|
||||
keys: vec![
|
||||
(alice(), to_session_keys(
|
||||
&Ed25519Keyring::Alice,
|
||||
&Sr25519Keyring::Alice,
|
||||
)),
|
||||
(bob(), to_session_keys(
|
||||
&Ed25519Keyring::Bob,
|
||||
&Sr25519Keyring::Bob,
|
||||
)),
|
||||
(charlie(), to_session_keys(
|
||||
&Ed25519Keyring::Charlie,
|
||||
&Sr25519Keyring::Charlie,
|
||||
)),
|
||||
]
|
||||
}),
|
||||
pallet_staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
stakers: vec![
|
||||
(dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator),
|
||||
(eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator),
|
||||
(ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator)
|
||||
],
|
||||
validator_count: 3,
|
||||
minimum_validator_count: 0,
|
||||
slash_reward_fraction: Perbill::from_percent(10),
|
||||
invulnerables: vec![alice(), bob(), charlie()],
|
||||
.. Default::default()
|
||||
}),
|
||||
pallet_contracts: Some(ContractsConfig {
|
||||
current_schedule: Default::default(),
|
||||
gas_price: 1 * MILLICENTS,
|
||||
}),
|
||||
pallet_babe: Some(Default::default()),
|
||||
pallet_grandpa: Some(GrandpaConfig {
|
||||
authorities: vec![],
|
||||
}),
|
||||
pallet_im_online: Some(Default::default()),
|
||||
pallet_authority_discovery: Some(Default::default()),
|
||||
pallet_democracy: Some(Default::default()),
|
||||
pallet_collective_Instance1: Some(Default::default()),
|
||||
pallet_collective_Instance2: Some(Default::default()),
|
||||
pallet_membership_Instance1: Some(Default::default()),
|
||||
pallet_sudo: Some(Default::default()),
|
||||
pallet_treasury: Some(Default::default()),
|
||||
// here comes configuration for Kovan chain
|
||||
// TODO: Update Name
|
||||
bridge_eth_poa: Some(BridgeEthPoaConfig {
|
||||
initial_header: sp_bridge_eth_poa::Header {
|
||||
parent_hash: Default::default(),
|
||||
timestamp: 0,
|
||||
number: 0,
|
||||
author: Default::default(),
|
||||
transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(),
|
||||
uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(),
|
||||
extra_data: vec![],
|
||||
state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(),
|
||||
receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(),
|
||||
log_bloom: Default::default(),
|
||||
gas_used: Default::default(),
|
||||
gas_limit: 6000000.into(),
|
||||
difficulty: 131072.into(),
|
||||
seal: vec![
|
||||
vec![128].into(),
|
||||
vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(),
|
||||
],
|
||||
},
|
||||
initial_difficulty: 0.into(),
|
||||
initial_validators: vec![
|
||||
[0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58,
|
||||
0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(),
|
||||
[0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d,
|
||||
0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(),
|
||||
[0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8,
|
||||
0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(),
|
||||
[0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60,
|
||||
0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(),
|
||||
[0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5,
|
||||
0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(),
|
||||
[0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9,
|
||||
0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(),
|
||||
[0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01,
|
||||
0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(),
|
||||
[0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C,
|
||||
0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(),
|
||||
[0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c,
|
||||
0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(),
|
||||
],
|
||||
}),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user