removed unused files (#99)

This commit is contained in:
Svyatoslav Nikolsky
2020-05-18 17:11:46 +03:00
committed by Bastian Köcher
parent f42905186d
commit 7a3468a919
10 changed files with 0 additions and 3223 deletions
@@ -1,128 +0,0 @@
[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",
]
@@ -1,465 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Parity Bridges Common 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 Parity Bridges Common 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),
);
}
}
@@ -1,127 +0,0 @@
[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",
]
@@ -1,852 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! The Parity Bridges Common 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);
}
}
@@ -1,32 +0,0 @@
[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" }
@@ -1,160 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. 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(),
],
}),
}
}
@@ -1,101 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Parity Bridges Common Blake2b Hasher implementation
use hash_db::Hasher;
use hash256_std_hasher::Hash256StdHasher;
use crate::hash::H256;
pub mod blake2 {
use super::{Hasher, Hash256StdHasher, H256};
#[cfg(feature = "std")]
use crate::hashing::blake2_256;
#[cfg(not(feature = "std"))]
extern "C" {
fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8);
}
#[cfg(not(feature = "std"))]
fn blake2_256(data: &[u8]) -> [u8; 32] {
let mut result: [u8; 32] = Default::default();
unsafe {
ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
}
result
}
/// Concrete implementation of Hasher using Blake2b 256-bit hashes
#[derive(Debug)]
pub struct Blake2Hasher;
impl Hasher for Blake2Hasher {
type Out = H256;
type StdHasher = Hash256StdHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
blake2_256(x).into()
}
}
}
pub mod keccak256 {
use super::{Hasher, Hash256StdHasher, H256};
#[cfg(feature = "std")]
use crate::hashing::keccak_256;
#[cfg(not(feature = "std"))]
extern "C" {
fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8);
}
#[cfg(not(feature = "std"))]
fn keccak_256(data: &[u8]) -> [u8; 32] {
let mut result: [u8; 32] = Default::default();
unsafe {
ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
}
result
}
/// Concrete implementation of Hasher using Keccak 256-bit hashes
#[derive(Debug)]
pub struct Keccak256Hasher;
impl Hasher for Keccak256Hasher {
type Out = H256;
type StdHasher = Hash256StdHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
keccak_256(x).into()
}
}
}
@@ -1,328 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Shareable Parity Bridges Common types.
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
/// Initialize a key-value collection from array.
///
/// Creates a vector of given pairs and calls `collect` on the iterator from it.
/// Can be used to create a `HashMap`.
#[macro_export]
macro_rules! map {
($( $name:expr => $value:expr ),* $(,)? ) => (
vec![ $( ( $name, $value ) ),* ].into_iter().collect()
);
}
use sp_std::prelude::*;
use sp_std::ops::Deref;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "std")]
pub use serde;
#[doc(hidden)]
pub use codec::{Encode, Decode};
pub use sp_debug_derive::RuntimeDebug;
#[cfg(feature = "std")]
pub use impl_serde::serialize as bytes;
#[cfg(feature = "full_crypto")]
pub mod hashing;
#[cfg(feature = "full_crypto")]
pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256, keccak_256};
#[cfg(feature = "std")]
pub mod hexdisplay;
pub mod crypto;
pub mod u32_trait;
pub mod ed25519;
pub mod sr25519;
pub mod ecdsa;
pub mod hash;
mod hasher;
pub mod offchain;
pub mod sandbox;
pub mod uint;
mod changes_trie;
#[cfg(feature = "std")]
pub mod traits;
pub mod testing;
#[cfg(test)]
mod tests;
pub use self::hash::{H160, H256, H512, convert_hash};
pub use self::uint::U256;
pub use changes_trie::ChangesTrieConfiguration;
#[cfg(feature = "full_crypto")]
pub use crypto::{DeriveJunction, Pair, Public};
pub use hash_db::Hasher;
// Switch back to Blake after PoC-3 is out
// pub use self::hasher::blake::BlakeHasher;
pub use self::hasher::blake2::Blake2Hasher;
pub use self::hasher::keccak256::Keccak256Hasher;
pub use sp_storage as storage;
#[doc(hidden)]
pub use sp_std;
/// Context for executing a call into the runtime.
pub enum ExecutionContext {
/// Context for general importing (including own blocks).
Importing,
/// Context used when syncing the blockchain.
Syncing,
/// Context used for block construction.
BlockConstruction,
/// Context used for offchain calls.
///
/// This allows passing offchain extension and customizing available capabilities.
OffchainCall(Option<(Box<dyn offchain::Externalities>, offchain::Capabilities)>),
}
impl ExecutionContext {
/// Returns the capabilities of particular context.
pub fn capabilities(&self) -> offchain::Capabilities {
use ExecutionContext::*;
match self {
Importing | Syncing | BlockConstruction =>
offchain::Capabilities::none(),
// Enable keystore by default for offchain calls. CC @bkchr
OffchainCall(None) => [offchain::Capability::Keystore][..].into(),
OffchainCall(Some((_, capabilities))) => *capabilities,
}
}
}
/// Hex-serialized shim for `Vec<u8>`.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))]
pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl From<Vec<u8>> for Bytes {
fn from(s: Vec<u8>) -> Self { Bytes(s) }
}
impl From<OpaqueMetadata> for Bytes {
fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) }
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.0[..] }
}
/// Stores the encoded `RuntimeMetadata` for the native side as opaque type.
#[derive(Encode, Decode, PartialEq)]
pub struct OpaqueMetadata(Vec<u8>);
impl OpaqueMetadata {
/// Creates a new instance with the given metadata blob.
pub fn new(metadata: Vec<u8>) -> Self {
OpaqueMetadata(metadata)
}
}
impl sp_std::ops::Deref for OpaqueMetadata {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// Something that is either a native or an encoded value.
#[cfg(feature = "std")]
pub enum NativeOrEncoded<R> {
/// The native representation.
Native(R),
/// The encoded representation.
Encoded(Vec<u8>)
}
#[cfg(feature = "std")]
impl<R: codec::Encode> sp_std::fmt::Debug for NativeOrEncoded<R> {
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f)
}
}
#[cfg(feature = "std")]
impl<R: codec::Encode> NativeOrEncoded<R> {
/// Return the value as the encoded format.
pub fn as_encoded(&self) -> Cow<'_, [u8]> {
match self {
NativeOrEncoded::Encoded(e) => Cow::Borrowed(e.as_slice()),
NativeOrEncoded::Native(n) => Cow::Owned(n.encode()),
}
}
/// Return the value as the encoded format.
pub fn into_encoded(self) -> Vec<u8> {
match self {
NativeOrEncoded::Encoded(e) => e,
NativeOrEncoded::Native(n) => n.encode(),
}
}
}
#[cfg(feature = "std")]
impl<R: PartialEq + codec::Decode> PartialEq for NativeOrEncoded<R> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(NativeOrEncoded::Native(l), NativeOrEncoded::Native(r)) => l == r,
(NativeOrEncoded::Native(n), NativeOrEncoded::Encoded(e)) |
(NativeOrEncoded::Encoded(e), NativeOrEncoded::Native(n)) =>
Some(n) == codec::Decode::decode(&mut &e[..]).ok().as_ref(),
(NativeOrEncoded::Encoded(l), NativeOrEncoded::Encoded(r)) => l == r,
}
}
}
/// A value that is never in a native representation.
/// This is type is useful in conjuction with `NativeOrEncoded`.
#[cfg(feature = "std")]
#[derive(PartialEq)]
pub enum NeverNativeValue {}
#[cfg(feature = "std")]
impl codec::Encode for NeverNativeValue {
fn encode(&self) -> Vec<u8> {
// The enum is not constructable, so this function should never be callable!
unreachable!()
}
}
#[cfg(feature = "std")]
impl codec::EncodeLike for NeverNativeValue {}
#[cfg(feature = "std")]
impl codec::Decode for NeverNativeValue {
fn decode<I: codec::Input>(_: &mut I) -> Result<Self, codec::Error> {
Err("`NeverNativeValue` should never be decoded".into())
}
}
/// Provide a simple 4 byte identifier for a type.
pub trait TypeId {
/// Simple 4 byte identifier.
const TYPE_ID: [u8; 4];
}
/// A log level matching the one from `log` crate.
///
/// Used internally by `sp_io::log` method.
#[derive(Encode, Decode, sp_runtime_interface::pass_by::PassByEnum, Copy, Clone)]
pub enum LogLevel {
/// `Error` log level.
Error = 1,
/// `Warn` log level.
Warn = 2,
/// `Info` log level.
Info = 3,
/// `Debug` log level.
Debug = 4,
/// `Trace` log level.
Trace = 5,
}
impl From<u32> for LogLevel {
fn from(val: u32) -> Self {
match val {
x if x == LogLevel::Warn as u32 => LogLevel::Warn,
x if x == LogLevel::Info as u32 => LogLevel::Info,
x if x == LogLevel::Debug as u32 => LogLevel::Debug,
x if x == LogLevel::Trace as u32 => LogLevel::Trace,
_ => LogLevel::Error,
}
}
}
impl From<log::Level> for LogLevel {
fn from(l: log::Level) -> Self {
use log::Level::*;
match l {
Error => Self::Error,
Warn => Self::Warn,
Info => Self::Info,
Debug => Self::Debug,
Trace => Self::Trace,
}
}
}
impl From<LogLevel> for log::Level {
fn from(l: LogLevel) -> Self {
use self::LogLevel::*;
match l {
Error => Self::Error,
Warn => Self::Warn,
Info => Self::Info,
Debug => Self::Debug,
Trace => Self::Trace,
}
}
}
/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`.
///
/// When Parity Bridges Common calls into Wasm it expects a fixed signature for functions exported
/// from the Wasm blob. The return value of this signature is always a `u64`.
/// This `u64` stores the pointer to the encoded return value and the length of this encoded value.
/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length.
#[cfg(not(feature = "std"))]
pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 {
let encoded = value.encode();
let ptr = encoded.as_ptr() as u64;
let length = encoded.len() as u64;
let res = ptr | (length << 32);
// Leak the output vector to avoid it being freed.
// This is fine in a WASM context since the heap
// will be discarded after the call.
sp_std::mem::forget(encoded);
res
}
@@ -1,40 +0,0 @@
[package]
name = "sp-io"
version = "2.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false }
hash-db = { version = "0.15.2", default-features = false }
sp-core = { version = "2.0.0", default-features = false, path = "../core" }
sp-std = { version = "2.0.0", default-features = false, path = "../std" }
libsecp256k1 = { version = "0.3.4", optional = true }
sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" }
sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../runtime-interface" }
sp-trie = { version = "2.0.0", optional = true, path = "../../primitives/trie" }
sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" }
log = { version = "0.4.8", optional = true }
[features]
default = ["std"]
std = [
"sp-core/std",
"codec/std",
"sp-std/std",
"hash-db/std",
"sp-trie",
"sp-state-machine",
"libsecp256k1",
"sp-runtime-interface/std",
"sp-externalities",
"log",
]
# These two features are used for `no_std` builds for the environments which already provides
# `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`.
#
# For the regular wasm runtime builds those are not used.
disable_panic_handler = []
disable_oom = []
disable_allocator = []
@@ -1,990 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! This is part of the Parity Bridges Common runtime.
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))]
#![cfg_attr(not(feature = "std"), feature(core_intrinsics))]
#![cfg_attr(feature = "std",
doc = "Parity Bridges Common runtime standard library as compiled when linked with Rust's standard library.")]
#![cfg_attr(not(feature = "std"),
doc = "Parity Bridges Common's runtime standard library as compiled without Rust's standard library.")]
use sp_std::vec::Vec;
#[cfg(feature = "std")]
use sp_std::ops::Deref;
#[cfg(feature = "std")]
use sp_core::{
crypto::Pair,
traits::KeystoreExt,
offchain::{OffchainExt, TransactionPoolExt},
hexdisplay::HexDisplay,
storage::{ChildStorageKey, ChildInfo},
};
use sp_core::{
crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel,
offchain::{
Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState,
},
};
#[cfg(feature = "std")]
use ::sp_trie::{TrieConfiguration, trie_types::Layout};
use sp_runtime_interface::{runtime_interface, Pointer};
use codec::{Encode, Decode};
#[cfg(feature = "std")]
use sp_externalities::{ExternalitiesExt, Externalities};
/// Error verifying ECDSA signature
#[derive(Encode, Decode)]
pub enum EcdsaVerifyError {
/// Incorrect value of R or S
BadRS,
/// Incorrect value of V
BadV,
/// Invalid signature
BadSignature,
}
/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage
/// key or panics otherwise.
///
/// Panicking here is aligned with what the `without_std` environment would do
/// in the case of an invalid child storage key.
#[cfg(feature = "std")]
fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey {
match ChildStorageKey::from_slice(storage_key) {
Some(storage_key) => storage_key,
None => panic!("child storage key is invalid"),
}
}
/// Interface for accessing the storage from within the runtime.
#[runtime_interface]
pub trait Storage {
/// Returns the data for `key` in the storage or `None` if the key can not be found.
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.storage(key).map(|s| s.to_vec())
}
/// All Child api uses :
/// - A `child_storage_key` to define the anchor point for the child proof
/// (commonly the location where the child root is stored in its parent trie).
/// - A `child_storage_types` to identify the kind of the child type and how its
/// `child definition` parameter is encoded.
/// - A `child_definition_parameter` which is the additional information required
/// to use the child trie. For instance defaults child tries requires this to
/// contain a collision free unique id.
///
/// This function specifically returns the data for `key` in the child storage or `None`
/// if the key can not be found.
fn child_get(
&self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
) -> Option<Vec<u8>> {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.child_storage(storage_key, child_info, key).map(|s| s.to_vec())
}
/// Get `key` from storage, placing the value into `value_out` and return the number of
/// bytes that the entry in storage has beyond the offset or `None` if the storage entry
/// doesn't exist at all.
/// If `value_out` length is smaller than the returned length, only `value_out` length bytes
/// are copied into `value_out`.
fn read(&self, key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option<u32> {
self.storage(key).map(|value| {
let value_offset = value_offset as usize;
let data = &value[value_offset.min(value.len())..];
let written = std::cmp::min(data.len(), value_out.len());
value_out[..written].copy_from_slice(&data[..written]);
value.len() as u32
})
}
/// Get `key` from child storage, placing the value into `value_out` and return the number
/// of bytes that the entry in storage has beyond the offset or `None` if the storage entry
/// doesn't exist at all.
/// If `value_out` length is smaller than the returned length, only `value_out` length bytes
/// are copied into `value_out`.
///
/// See `child_get` for common child api parameters.
fn child_read(
&self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
value_out: &mut [u8],
value_offset: u32,
) -> Option<u32> {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.child_storage(storage_key, child_info, key)
.map(|value| {
let value_offset = value_offset as usize;
let data = &value[value_offset.min(value.len())..];
let written = std::cmp::min(data.len(), value_out.len());
value_out[..written].copy_from_slice(&data[..written]);
value.len() as u32
})
}
/// Set `key` to `value` in the storage.
fn set(&mut self, key: &[u8], value: &[u8]) {
self.set_storage(key.to_vec(), value.to_vec());
}
/// Set `key` to `value` in the child storage denoted by `child_storage_key`.
///
/// See `child_get` for common child api parameters.
fn child_set(
&mut self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
value: &[u8],
) {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec());
}
/// Clear the storage of the given `key` and its value.
fn clear(&mut self, key: &[u8]) {
self.clear_storage(key)
}
/// Clear the given child storage of the given `key` and its value.
///
/// See `child_get` for common child api parameters.
fn child_clear(
&mut self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
) {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.clear_child_storage(storage_key, child_info, key);
}
/// Clear an entire child storage.
///
/// See `child_get` for common child api parameters.
fn child_storage_kill(
&mut self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
) {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.kill_child_storage(storage_key, child_info);
}
/// Check whether the given `key` exists in storage.
fn exists(&self, key: &[u8]) -> bool {
self.exists_storage(key)
}
/// Check whether the given `key` exists in storage.
///
/// See `child_get` for common child api parameters.
fn child_exists(
&self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
) -> bool {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.exists_child_storage(storage_key, child_info, key)
}
/// Clear the storage of each key-value pair where the key starts with the given `prefix`.
fn clear_prefix(&mut self, prefix: &[u8]) {
Externalities::clear_prefix(*self, prefix)
}
/// Clear the child storage of each key-value pair where the key starts with the given `prefix`.
///
/// See `child_get` for common child api parameters.
fn child_clear_prefix(
&mut self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
prefix: &[u8],
) {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.clear_child_prefix(storage_key, child_info, prefix);
}
/// "Commit" all existing operations and compute the resulting storage root.
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
fn root(&mut self) -> Vec<u8> {
self.storage_root()
}
/// "Commit" all existing operations and compute the resulting child storage root.
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
///
/// See `child_get` for common child api parameters.
fn child_root(
&mut self,
child_storage_key: &[u8],
) -> Vec<u8> {
let storage_key = child_storage_key_or_panic(child_storage_key);
self.child_storage_root(storage_key)
}
/// "Commit" all existing operations and get the resulting storage change root.
/// `parent_hash` is a SCALE encoded hash.
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn changes_root(&mut self, parent_hash: &[u8]) -> Option<Vec<u8>> {
self.storage_changes_root(parent_hash)
.expect("Invalid `parent_hash` given to `changes_root`.")
}
/// Get the next key in storage after the given one in lexicographic order.
fn next_key(&mut self, key: &[u8]) -> Option<Vec<u8>> {
self.next_storage_key(&key)
}
/// Get the next key in storage after the given one in lexicographic order in child storage.
fn child_next_key(
&mut self,
child_storage_key: &[u8],
child_definition: &[u8],
child_type: u32,
key: &[u8],
) -> Option<Vec<u8>> {
let storage_key = child_storage_key_or_panic(child_storage_key);
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
.expect("Invalid child definition");
self.next_child_storage_key(storage_key, child_info, key)
}
}
/// Interface that provides trie related functionality.
#[runtime_interface]
pub trait Trie {
/// A trie root formed from the iterated items.
fn blake2_256_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
Layout::<sp_core::Blake2Hasher>::trie_root(input)
}
/// A trie root formed from the enumerated items.
fn blake2_256_ordered_root(input: Vec<Vec<u8>>) -> H256 {
Layout::<sp_core::Blake2Hasher>::ordered_trie_root(input)
}
/// A trie root formed from the enumerated items.
fn keccak_256_ordered_root(input: Vec<Vec<u8>>) -> H256 {
Layout::<sp_core::Keccak256Hasher>::ordered_trie_root(input)
}
}
/// Interface that provides miscellaneous functions for communicating between the runtime and the node.
#[runtime_interface]
pub trait Misc {
/// The current relay chain identifier.
fn chain_id(&self) -> u64 {
sp_externalities::Externalities::chain_id(*self)
}
/// Print a number.
fn print_num(val: u64) {
log::debug!(target: "runtime", "{}", val);
}
/// Print any valid `utf8` buffer.
fn print_utf8(utf8: &[u8]) {
if let Ok(data) = std::str::from_utf8(utf8) {
log::debug!(target: "runtime", "{}", data)
}
}
/// Print any `u8` slice as hex.
fn print_hex(data: &[u8]) {
log::debug!(target: "runtime", "{}", HexDisplay::from(&data));
}
}
/// Interfaces for working with crypto related types from within the runtime.
#[runtime_interface]
pub trait Crypto {
/// Returns all `ed25519` public keys for the given key id from the keystore.
fn ed25519_public_keys(&mut self, id: KeyTypeId) -> Vec<ed25519::Public> {
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.read()
.ed25519_public_keys(id)
}
/// Generate an `ed22519` key for the given key type using an optional `seed` and
/// store it in the keystore.
///
/// The `seed` needs to be a valid utf8.
///
/// Returns the public key.
fn ed25519_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> ed25519::Public {
let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!"));
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.write()
.ed25519_generate_new(id, seed)
.expect("`ed25519_generate` failed")
}
/// Sign the given `msg` with the `ed25519` key that corresponds to the given public key and
/// key type in the keystore.
///
/// Returns the signature.
fn ed25519_sign(
&mut self,
id: KeyTypeId,
pub_key: &ed25519::Public,
msg: &[u8],
) -> Option<ed25519::Signature> {
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.read()
.ed25519_key_pair(id, &pub_key)
.map(|k| k.sign(msg))
}
/// Verify an `ed25519` signature.
///
/// Returns `true` when the verification in successful.
fn ed25519_verify(
&self,
sig: &ed25519::Signature,
msg: &[u8],
pub_key: &ed25519::Public,
) -> bool {
ed25519::Pair::verify(sig, msg, pub_key)
}
/// Returns all `sr25519` public keys for the given key id from the keystore.
fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec<sr25519::Public> {
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.read()
.sr25519_public_keys(id)
}
/// Generate an `sr22519` key for the given key type using an optional seed and
/// store it in the keystore.
///
/// The `seed` needs to be a valid utf8.
///
/// Returns the public key.
fn sr25519_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> sr25519::Public {
let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!"));
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.write()
.sr25519_generate_new(id, seed)
.expect("`sr25519_generate` failed")
}
/// Sign the given `msg` with the `sr25519` key that corresponds to the given public key and
/// key type in the keystore.
///
/// Returns the signature.
fn sr25519_sign(
&mut self,
id: KeyTypeId,
pub_key: &sr25519::Public,
msg: &[u8],
) -> Option<sr25519::Signature> {
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.read()
.sr25519_key_pair(id, &pub_key)
.map(|k| k.sign(msg))
}
/// Verify an `sr25519` signature.
///
/// Returns `true` when the verification in successful.
fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool {
sr25519::Pair::verify(sig, msg, pubkey)
}
/// Verify and recover a SECP256k1 ECDSA signature.
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
/// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey
/// (doesn't include the 0x04 prefix).
fn secp256k1_ecdsa_recover(
sig: &[u8; 65],
msg: &[u8; 32],
) -> Result<[u8; 64], EcdsaVerifyError> {
let rs = secp256k1::Signature::parse_slice(&sig[0..64])
.map_err(|_| EcdsaVerifyError::BadRS)?;
let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8)
.map_err(|_| EcdsaVerifyError::BadV)?;
let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v)
.map_err(|_| EcdsaVerifyError::BadSignature)?;
let mut res = [0u8; 64];
res.copy_from_slice(&pubkey.serialize()[1..65]);
Ok(res)
}
/// Verify and recover a SECP256k1 ECDSA signature.
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
/// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey.
fn secp256k1_ecdsa_recover_compressed(
sig: &[u8; 65],
msg: &[u8; 32],
) -> Result<[u8; 33], EcdsaVerifyError> {
let rs = secp256k1::Signature::parse_slice(&sig[0..64])
.map_err(|_| EcdsaVerifyError::BadRS)?;
let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8)
.map_err(|_| EcdsaVerifyError::BadV)?;
let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v)
.map_err(|_| EcdsaVerifyError::BadSignature)?;
Ok(pubkey.serialize_compressed())
}
}
/// Interface that provides functions for hashing with different algorithms.
#[runtime_interface]
pub trait Hashing {
/// Conduct a 256-bit Keccak hash.
fn keccak_256(data: &[u8]) -> [u8; 32] {
sp_core::hashing::keccak_256(data)
}
/// Conduct a 256-bit Sha2 hash.
fn sha2_256(data: &[u8]) -> [u8; 32] {
sp_core::hashing::sha2_256(data)
}
/// Conduct a 128-bit Blake2 hash.
fn blake2_128(data: &[u8]) -> [u8; 16] {
sp_core::hashing::blake2_128(data)
}
/// Conduct a 256-bit Blake2 hash.
fn blake2_256(data: &[u8]) -> [u8; 32] {
sp_core::hashing::blake2_256(data)
}
/// Conduct four XX hashes to give a 256-bit result.
fn twox_256(data: &[u8]) -> [u8; 32] {
sp_core::hashing::twox_256(data)
}
/// Conduct two XX hashes to give a 128-bit result.
fn twox_128(data: &[u8]) -> [u8; 16] {
sp_core::hashing::twox_128(data)
}
/// Conduct two XX hashes to give a 64-bit result.
fn twox_64(data: &[u8]) -> [u8; 8] {
sp_core::hashing::twox_64(data)
}
}
/// Interface that provides functions to access the offchain functionality.
#[runtime_interface]
pub trait Offchain {
/// Returns if the local node is a potential validator.
///
/// Even if this function returns `true`, it does not mean that any keys are configured
/// and that the validator is registered in the chain.
fn is_validator(&mut self) -> bool {
self.extension::<OffchainExt>()
.expect("is_validator can be called only in the offchain worker context")
.is_validator()
}
/// Submit an encoded transaction to the pool.
///
/// The transaction will end up in the pool.
fn submit_transaction(&mut self, data: Vec<u8>) -> Result<(), ()> {
self.extension::<TransactionPoolExt>()
.expect("submit_transaction can be called only in the offchain call context with
TransactionPool capabilities enabled")
.submit_transaction(data)
}
/// Returns information about the local node's network state.
fn network_state(&mut self) -> Result<OpaqueNetworkState, ()> {
self.extension::<OffchainExt>()
.expect("network_state can be called only in the offchain worker context")
.network_state()
}
/// Returns current UNIX timestamp (in millis)
fn timestamp(&mut self) -> Timestamp {
self.extension::<OffchainExt>()
.expect("timestamp can be called only in the offchain worker context")
.timestamp()
}
/// Pause the execution until `deadline` is reached.
fn sleep_until(&mut self, deadline: Timestamp) {
self.extension::<OffchainExt>()
.expect("sleep_until can be called only in the offchain worker context")
.sleep_until(deadline)
}
/// Returns a random seed.
///
/// This is a trully random non deterministic seed generated by host environment.
/// Obviously fine in the off-chain worker context.
fn random_seed(&mut self) -> [u8; 32] {
self.extension::<OffchainExt>()
.expect("random_seed can be called only in the offchain worker context")
.random_seed()
}
/// Sets a value in the local storage.
///
/// Note this storage is not part of the consensus, it's only accessible by
/// offchain worker tasks running on the same machine. It IS persisted between runs.
fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) {
self.extension::<OffchainExt>()
.expect("local_storage_set can be called only in the offchain worker context")
.local_storage_set(kind, key, value)
}
/// Sets a value in the local storage if it matches current value.
///
/// Since multiple offchain workers may be running concurrently, to prevent
/// data races use CAS to coordinate between them.
///
/// Returns `true` if the value has been set, `false` otherwise.
///
/// Note this storage is not part of the consensus, it's only accessible by
/// offchain worker tasks running on the same machine. It IS persisted between runs.
fn local_storage_compare_and_set(
&mut self,
kind: StorageKind,
key: &[u8],
old_value: Option<Vec<u8>>,
new_value: &[u8],
) -> bool {
self.extension::<OffchainExt>()
.expect("local_storage_compare_and_set can be called only in the offchain worker context")
.local_storage_compare_and_set(kind, key, old_value.as_ref().map(|v| v.deref()), new_value)
}
/// Gets a value from the local storage.
///
/// If the value does not exist in the storage `None` will be returned.
/// Note this storage is not part of the consensus, it's only accessible by
/// offchain worker tasks running on the same machine. It IS persisted between runs.
fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option<Vec<u8>> {
self.extension::<OffchainExt>()
.expect("local_storage_get can be called only in the offchain worker context")
.local_storage_get(kind, key)
}
/// Initiates a http request given HTTP verb and the URL.
///
/// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters.
/// Returns the id of newly started request.
fn http_request_start(
&mut self,
method: &str,
uri: &str,
meta: &[u8],
) -> Result<HttpRequestId, ()> {
self.extension::<OffchainExt>()
.expect("http_request_start can be called only in the offchain worker context")
.http_request_start(method, uri, meta)
}
/// Append header to the request.
fn http_request_add_header(
&mut self,
request_id: HttpRequestId,
name: &str,
value: &str,
) -> Result<(), ()> {
self.extension::<OffchainExt>()
.expect("http_request_add_header can be called only in the offchain worker context")
.http_request_add_header(request_id, name, value)
}
/// Write a chunk of request body.
///
/// Writing an empty chunks finalizes the request.
/// Passing `None` as deadline blocks forever.
///
/// Returns an error in case deadline is reached or the chunk couldn't be written.
fn http_request_write_body(
&mut self,
request_id: HttpRequestId,
chunk: &[u8],
deadline: Option<Timestamp>,
) -> Result<(), HttpError> {
self.extension::<OffchainExt>()
.expect("http_request_write_body can be called only in the offchain worker context")
.http_request_write_body(request_id, chunk, deadline)
}
/// Block and wait for the responses for given requests.
///
/// Returns a vector of request statuses (the len is the same as ids).
/// Note that if deadline is not provided the method will block indefinitely,
/// otherwise unready responses will produce `DeadlineReached` status.
///
/// Passing `None` as deadline blocks forever.
fn http_response_wait(
&mut self,
ids: &[HttpRequestId],
deadline: Option<Timestamp>,
) -> Vec<HttpRequestStatus> {
self.extension::<OffchainExt>()
.expect("http_response_wait can be called only in the offchain worker context")
.http_response_wait(ids, deadline)
}
/// Read all response headers.
///
/// Returns a vector of pairs `(HeaderKey, HeaderValue)`.
/// NOTE response headers have to be read before response body.
fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec<u8>, Vec<u8>)> {
self.extension::<OffchainExt>()
.expect("http_response_headers can be called only in the offchain worker context")
.http_response_headers(request_id)
}
/// Read a chunk of body response to given buffer.
///
/// Returns the number of bytes written or an error in case a deadline
/// is reached or server closed the connection.
/// If `0` is returned it means that the response has been fully consumed
/// and the `request_id` is now invalid.
/// NOTE this implies that response headers must be read before draining the body.
/// Passing `None` as a deadline blocks forever.
fn http_response_read_body(
&mut self,
request_id: HttpRequestId,
buffer: &mut [u8],
deadline: Option<Timestamp>,
) -> Result<u32, HttpError> {
self.extension::<OffchainExt>()
.expect("http_response_read_body can be called only in the offchain worker context")
.http_response_read_body(request_id, buffer, deadline)
.map(|r| r as u32)
}
}
/// Wasm only interface that provides functions for calling into the allocator.
#[runtime_interface(wasm_only)]
trait Allocator {
/// Malloc the given number of bytes and return the pointer to the allocated memory location.
fn malloc(&mut self, size: u32) -> Pointer<u8> {
self.allocate_memory(size).expect("Failed to allocate memory")
}
/// Free the given pointer.
fn free(&mut self, ptr: Pointer<u8>) {
self.deallocate_memory(ptr).expect("Failed to deallocate memory")
}
}
/// Interface that provides functions for logging from within the runtime.
#[runtime_interface]
pub trait Logging {
/// Request to print a log message on the host.
///
/// Note that this will be only displayed if the host is enabled to display log messages with
/// given level and target.
///
/// Instead of using directly, prefer setting up `RuntimeLogger` and using `log` macros.
fn log(level: LogLevel, target: &str, message: &[u8]) {
if let Ok(message) = std::str::from_utf8(message) {
log::log!(
target: target,
log::Level::from(level),
"{}",
message,
)
}
}
}
/// Wasm-only interface that provides functions for interacting with the sandbox.
#[runtime_interface(wasm_only)]
pub trait Sandbox {
/// Instantiate a new sandbox instance with the given `wasm_code`.
fn instantiate(
&mut self,
dispatch_thunk: u32,
wasm_code: &[u8],
env_def: &[u8],
state_ptr: Pointer<u8>,
) -> u32 {
self.sandbox()
.instance_new(dispatch_thunk, wasm_code, env_def, state_ptr.into())
.expect("Failed to instantiate a new sandbox")
}
/// Invoke `function` in the sandbox with `sandbox_idx`.
fn invoke(
&mut self,
instance_idx: u32,
function: &str,
args: &[u8],
return_val_ptr: Pointer<u8>,
return_val_len: u32,
state_ptr: Pointer<u8>,
) -> u32 {
self.sandbox().invoke(
instance_idx,
&function,
&args,
return_val_ptr,
return_val_len,
state_ptr.into(),
).expect("Failed to invoke function with sandbox")
}
/// Create a new memory instance with the given `initial` and `maximum` size.
fn memory_new(&mut self, initial: u32, maximum: u32) -> u32 {
self.sandbox()
.memory_new(initial, maximum)
.expect("Failed to create new memory with sandbox")
}
/// Get the memory starting at `offset` from the instance with `memory_idx` into the buffer.
fn memory_get(
&mut self,
memory_idx: u32,
offset: u32,
buf_ptr: Pointer<u8>,
buf_len: u32,
) -> u32 {
self.sandbox()
.memory_get(memory_idx, offset, buf_ptr, buf_len)
.expect("Failed to get memory with sandbox")
}
/// Set the memory in the given `memory_idx` to the given value at `offset`.
fn memory_set(
&mut self,
memory_idx: u32,
offset: u32,
val_ptr: Pointer<u8>,
val_len: u32,
) -> u32 {
self.sandbox()
.memory_set(memory_idx, offset, val_ptr, val_len)
.expect("Failed to set memory with sandbox")
}
/// Teardown the memory instance with the given `memory_idx`.
fn memory_teardown(&mut self, memory_idx: u32) {
self.sandbox().memory_teardown(memory_idx).expect("Failed to teardown memory with sandbox")
}
/// Teardown the sandbox instance with the given `instance_idx`.
fn instance_teardown(&mut self, instance_idx: u32) {
self.sandbox().instance_teardown(instance_idx).expect("Failed to teardown sandbox instance")
}
}
/// Allocator used by Parity Bridges Common when executing the Wasm runtime.
#[cfg(not(feature = "std"))]
struct WasmAllocator;
#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))]
#[global_allocator]
static ALLOCATOR: WasmAllocator = WasmAllocator;
#[cfg(not(feature = "std"))]
mod allocator_impl {
use super::*;
use core::alloc::{GlobalAlloc, Layout};
unsafe impl GlobalAlloc for WasmAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
allocator::malloc(layout.size() as u32)
}
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
allocator::free(ptr)
}
}
}
/// A default panic handler for WASM environment.
#[cfg(all(not(feature = "disable_panic_handler"), not(feature = "std")))]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &core::panic::PanicInfo) -> ! {
unsafe {
let message = sp_std::alloc::format!("{}", info);
logging::log(LogLevel::Error, "runtime", message.as_bytes());
core::intrinsics::abort()
}
}
/// A default OOM handler for WASM environment.
#[cfg(all(not(feature = "disable_oom"), not(feature = "std")))]
#[alloc_error_handler]
pub fn oom(_: core::alloc::Layout) -> ! {
unsafe {
logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting");
core::intrinsics::abort();
}
}
/// Type alias for Externalities implementation used in tests.
#[cfg(feature = "std")]
pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher, u64>;
/// The host functions Parity Bridges Common provides for the Wasm runtime environment.
///
/// All these host functions will be callable from inside the Wasm environment.
#[cfg(feature = "std")]
pub type Parity Bridges CommonHostFunctions = (
storage::HostFunctions,
misc::HostFunctions,
offchain::HostFunctions,
crypto::HostFunctions,
hashing::HostFunctions,
allocator::HostFunctions,
logging::HostFunctions,
sandbox::HostFunctions,
crate::trie::HostFunctions,
);
#[cfg(test)]
mod tests {
use super::*;
use sp_core::map;
use sp_state_machine::BasicExternalities;
use sp_core::storage::Storage;
#[test]
fn storage_works() {
let mut t = BasicExternalities::default();
t.execute_with(|| {
assert_eq!(storage::get(b"hello"), None);
storage::set(b"hello", b"world");
assert_eq!(storage::get(b"hello"), Some(b"world".to_vec()));
assert_eq!(storage::get(b"foo"), None);
storage::set(b"foo", &[1, 2, 3][..]);
});
t = BasicExternalities::new(Storage {
top: map![b"foo".to_vec() => b"bar".to_vec()],
children: map![],
});
t.execute_with(|| {
assert_eq!(storage::get(b"hello"), None);
assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec()));
});
}
#[test]
fn read_storage_works() {
let mut t = BasicExternalities::new(Storage {
top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()],
children: map![],
});
t.execute_with(|| {
let mut v = [0u8; 4];
assert!(storage::read(b":test", &mut v[..], 0).unwrap() >= 4);
assert_eq!(v, [11u8, 0, 0, 0]);
let mut w = [0u8; 11];
assert!(storage::read(b":test", &mut w[..], 4).unwrap() >= 11);
assert_eq!(&w, b"Hello world");
});
}
#[test]
fn clear_prefix_works() {
let mut t = BasicExternalities::new(Storage {
top: map![
b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
],
children: map![],
});
t.execute_with(|| {
storage::clear_prefix(b":abc");
assert!(storage::get(b":a").is_some());
assert!(storage::get(b":abdd").is_some());
assert!(storage::get(b":abcd").is_none());
assert!(storage::get(b":abc").is_none());
});
}
}