mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Merge pull request #4427 from paritytech/update-bridges-subtree-r/w
Update bridges subtree r/w
This commit is contained in:
@@ -10,13 +10,17 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
jsonrpc-core = "15.1.0"
|
||||
futures = "0.3"
|
||||
jsonrpc-core = "18.0"
|
||||
kvdb = "0.10"
|
||||
kvdb-rocksdb = "0.12"
|
||||
lru = "0.7"
|
||||
structopt = "0.3.21"
|
||||
serde_json = "1.0.59"
|
||||
thiserror = "1.0"
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-messages = { path = "../../../primitives/messages" }
|
||||
bp-runtime = { path = "../../../primitives/runtime" }
|
||||
bp-rialto = { path = "../../../primitives/chain-rialto" }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages" }
|
||||
@@ -24,32 +28,86 @@ rialto-runtime = { path = "../runtime" }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
|
||||
beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
#sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
# Polkadot Dependencies
|
||||
|
||||
polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
# Polkadot (parachain) Dependencies
|
||||
|
||||
polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -14,13 +14,17 @@
|
||||
// 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/>.
|
||||
|
||||
use beefy_primitives::crypto::AuthorityId as BeefyId;
|
||||
use bp_rialto::derive_account_from_millau_id;
|
||||
use polkadot_primitives::v1::{AssignmentId, ValidatorId};
|
||||
use rialto_runtime::{
|
||||
AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig,
|
||||
SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
|
||||
AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig,
|
||||
ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature,
|
||||
SudoConfig, SystemConfig, WASM_BINARY,
|
||||
};
|
||||
use serde_json::json;
|
||||
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use sp_consensus_babe::AuthorityId as BabeId;
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
use sp_finality_grandpa::AuthorityId as GrandpaId;
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
@@ -56,12 +60,18 @@ where
|
||||
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
|
||||
}
|
||||
|
||||
/// Helper function to generate an authority key for Aura
|
||||
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
|
||||
/// Helper function to generate authority keys.
|
||||
pub fn get_authority_keys_from_seed(
|
||||
s: &str,
|
||||
) -> (AccountId, BabeId, BeefyId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) {
|
||||
(
|
||||
get_account_id_from_seed::<sr25519::Public>(s),
|
||||
get_from_seed::<AuraId>(s),
|
||||
get_from_seed::<BabeId>(s),
|
||||
get_from_seed::<BeefyId>(s),
|
||||
get_from_seed::<GrandpaId>(s),
|
||||
get_from_seed::<ValidatorId>(s),
|
||||
get_from_seed::<AssignmentId>(s),
|
||||
get_from_seed::<AuthorityDiscoveryId>(s),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,10 +81,7 @@ impl Alternative {
|
||||
let properties = Some(
|
||||
json!({
|
||||
"tokenDecimals": 9,
|
||||
"tokenSymbol": "RLT",
|
||||
"bridgeIds": {
|
||||
"Millau": bp_runtime::MILLAU_CHAIN_ID,
|
||||
}
|
||||
"tokenSymbol": "RLT"
|
||||
})
|
||||
.as_object()
|
||||
.expect("Map given; qed")
|
||||
@@ -82,8 +89,8 @@ impl Alternative {
|
||||
);
|
||||
match self {
|
||||
Alternative::Development => ChainSpec::from_genesis(
|
||||
"Development",
|
||||
"dev",
|
||||
"Rialto Development",
|
||||
"rialto_dev",
|
||||
sc_service::ChainType::Development,
|
||||
|| {
|
||||
testnet_genesis(
|
||||
@@ -108,8 +115,8 @@ impl Alternative {
|
||||
None,
|
||||
),
|
||||
Alternative::LocalTestnet => ChainSpec::from_genesis(
|
||||
"Local Testnet",
|
||||
"local_testnet",
|
||||
"Rialto Local",
|
||||
"rialto_local",
|
||||
sc_service::ChainType::Local,
|
||||
|| {
|
||||
testnet_genesis(
|
||||
@@ -138,10 +145,12 @@ impl Alternative {
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("George//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Harry//stash"),
|
||||
pallet_bridge_messages::Pallet::<
|
||||
rialto_runtime::Runtime,
|
||||
pallet_bridge_messages::DefaultInstance,
|
||||
>::relayer_fund_account_id(),
|
||||
get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner"),
|
||||
get_account_id_from_seed::<sr25519::Public>("WithMillauTokenSwap"),
|
||||
pallet_bridge_messages::relayer_fund_account_id::<
|
||||
bp_rialto::AccountId,
|
||||
bp_rialto::AccountIdConverter,
|
||||
>(),
|
||||
derive_account_from_millau_id(bp_runtime::SourceAccount::Account(
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
)),
|
||||
@@ -174,12 +183,27 @@ impl Alternative {
|
||||
}
|
||||
}
|
||||
|
||||
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
|
||||
SessionKeys { aura, grandpa }
|
||||
fn session_keys(
|
||||
babe: BabeId,
|
||||
beefy: BeefyId,
|
||||
grandpa: GrandpaId,
|
||||
para_validator: ValidatorId,
|
||||
para_assignment: AssignmentId,
|
||||
authority_discovery: AuthorityDiscoveryId,
|
||||
) -> SessionKeys {
|
||||
SessionKeys { babe, beefy, grandpa, para_validator, para_assignment, authority_discovery }
|
||||
}
|
||||
|
||||
fn testnet_genesis(
|
||||
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>,
|
||||
initial_authorities: Vec<(
|
||||
AccountId,
|
||||
BabeId,
|
||||
BeefyId,
|
||||
GrandpaId,
|
||||
ValidatorId,
|
||||
AssignmentId,
|
||||
AuthorityDiscoveryId,
|
||||
)>,
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Vec<AccountId>,
|
||||
_enable_println: bool,
|
||||
@@ -187,51 +211,93 @@ fn testnet_genesis(
|
||||
GenesisConfig {
|
||||
system: SystemConfig {
|
||||
code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
},
|
||||
balances: BalancesConfig {
|
||||
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
|
||||
},
|
||||
aura: AuraConfig {
|
||||
authorities: Vec::new(),
|
||||
},
|
||||
bridge_rialto_poa: load_rialto_poa_bridge_config(),
|
||||
bridge_kovan: load_kovan_bridge_config(),
|
||||
grandpa: GrandpaConfig {
|
||||
babe: BabeConfig {
|
||||
authorities: Vec::new(),
|
||||
epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG),
|
||||
},
|
||||
beefy: BeefyConfig { authorities: Vec::new() },
|
||||
grandpa: GrandpaConfig { authorities: Vec::new() },
|
||||
sudo: SudoConfig { key: root_key },
|
||||
session: SessionConfig {
|
||||
keys: initial_authorities
|
||||
.iter()
|
||||
.map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())))
|
||||
.map(|x| {
|
||||
(
|
||||
x.0.clone(),
|
||||
x.0.clone(),
|
||||
session_keys(
|
||||
x.1.clone(),
|
||||
x.2.clone(),
|
||||
x.3.clone(),
|
||||
x.4.clone(),
|
||||
x.5.clone(),
|
||||
x.6.clone(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn load_rialto_poa_bridge_config() -> BridgeRialtoPoaConfig {
|
||||
BridgeRialtoPoaConfig {
|
||||
initial_header: rialto_runtime::rialto_poa::genesis_header(),
|
||||
initial_difficulty: 0.into(),
|
||||
initial_validators: rialto_runtime::rialto_poa::genesis_validators(),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_kovan_bridge_config() -> BridgeKovanConfig {
|
||||
BridgeKovanConfig {
|
||||
initial_header: rialto_runtime::kovan::genesis_header(),
|
||||
initial_difficulty: 0.into(),
|
||||
initial_validators: rialto_runtime::kovan::genesis_validators(),
|
||||
authority_discovery: Default::default(),
|
||||
hrmp: Default::default(),
|
||||
// this configuration is exact copy of configuration from Polkadot repo
|
||||
// (see /node/service/src/chain_spec.rs:default_parachains_host_configuration)
|
||||
configuration: ConfigurationConfig {
|
||||
config: polkadot_runtime_parachains::configuration::HostConfiguration {
|
||||
validation_upgrade_frequency: 1u32,
|
||||
validation_upgrade_delay: 1,
|
||||
code_retention_period: 1200,
|
||||
max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE,
|
||||
max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE,
|
||||
max_head_data_size: 32 * 1024,
|
||||
group_rotation_frequency: 20,
|
||||
chain_availability_period: 4,
|
||||
thread_availability_period: 4,
|
||||
max_upward_queue_count: 8,
|
||||
max_upward_queue_size: 1024 * 1024,
|
||||
max_downward_message_size: 1024,
|
||||
// this is approximatelly 4ms.
|
||||
//
|
||||
// Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with
|
||||
// an import since that's a made up number and should be replaced with a constant
|
||||
// obtained by benchmarking anyway.
|
||||
ump_service_total_weight: 4 * 1_000_000_000,
|
||||
max_upward_message_size: 1024 * 1024,
|
||||
max_upward_message_num_per_candidate: 5,
|
||||
hrmp_sender_deposit: 0,
|
||||
hrmp_recipient_deposit: 0,
|
||||
hrmp_channel_max_capacity: 8,
|
||||
hrmp_channel_max_total_size: 8 * 1024,
|
||||
hrmp_max_parachain_inbound_channels: 4,
|
||||
hrmp_max_parathread_inbound_channels: 4,
|
||||
hrmp_channel_max_message_size: 1024 * 1024,
|
||||
hrmp_max_parachain_outbound_channels: 4,
|
||||
hrmp_max_parathread_outbound_channels: 4,
|
||||
hrmp_max_message_num_per_candidate: 5,
|
||||
dispute_period: 6,
|
||||
no_show_slots: 2,
|
||||
n_delay_tranches: 25,
|
||||
needed_approvals: 2,
|
||||
relay_vrf_modulo_samples: 2,
|
||||
zeroth_delay_tranche_width: 0,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
paras: Default::default(),
|
||||
bridge_millau_messages: BridgeMillauMessagesConfig {
|
||||
owner: Some(get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner")),
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_dave_account_is_as_expected() {
|
||||
let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
|
||||
let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave));
|
||||
assert_eq!(
|
||||
derived.to_string(),
|
||||
"5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string()
|
||||
);
|
||||
let derived: AccountId =
|
||||
derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave));
|
||||
assert_eq!(derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string());
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ pub struct Cli {
|
||||
/// Possible subcommands of the main binary.
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum Subcommand {
|
||||
/// Key management cli utilities
|
||||
/// Key management CLI utilities
|
||||
Key(sc_cli::KeySubcommand),
|
||||
|
||||
/// Verify a signature for a message, provided on STDIN, with a given (public or secret) key.
|
||||
/// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key.
|
||||
Verify(sc_cli::VerifyCmd),
|
||||
|
||||
/// Generate a seed that provides a vanity address.
|
||||
@@ -67,4 +67,19 @@ pub enum Subcommand {
|
||||
|
||||
/// Benchmark runtime pallets.
|
||||
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
|
||||
|
||||
/// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary.
|
||||
#[structopt(name = "prepare-worker", setting = structopt::clap::AppSettings::Hidden)]
|
||||
PvfPrepareWorker(ValidationWorkerCommand),
|
||||
|
||||
/// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary.
|
||||
#[structopt(name = "execute-worker", setting = structopt::clap::AppSettings::Hidden)]
|
||||
PvfExecuteWorker(ValidationWorkerCommand),
|
||||
}
|
||||
|
||||
/// Validation worker command.
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub struct ValidationWorkerCommand {
|
||||
/// The path to the validation host's socket.
|
||||
pub socket_path: String,
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
// 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/>.
|
||||
|
||||
use crate::cli::{Cli, Subcommand};
|
||||
use crate::service;
|
||||
use crate::service::new_partial;
|
||||
use crate::{
|
||||
cli::{Cli, Subcommand},
|
||||
service::new_partial,
|
||||
};
|
||||
use rialto_runtime::{Block, RuntimeApi};
|
||||
use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli};
|
||||
use sc_service::PartialComponents;
|
||||
@@ -69,24 +70,23 @@ impl SubstrateCli for Cli {
|
||||
/// Parse and run command line arguments
|
||||
pub fn run() -> sc_cli::Result<()> {
|
||||
let cli = Cli::from_args();
|
||||
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom(
|
||||
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom(
|
||||
rialto_runtime::SS58Prefix::get() as u16,
|
||||
));
|
||||
|
||||
match &cli.subcommand {
|
||||
Some(Subcommand::Benchmark(cmd)) => {
|
||||
Some(Subcommand::Benchmark(cmd)) =>
|
||||
if cfg!(feature = "runtime-benchmarks") {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
|
||||
runner.sync_run(|config| cmd.run::<Block, service::Executor>(config))
|
||||
runner.sync_run(|config| cmd.run::<Block, crate::service::ExecutorDispatch>(config))
|
||||
} else {
|
||||
println!(
|
||||
"Benchmarking wasn't enabled when building the node. \
|
||||
You can enable it with `--features runtime-benchmarks`."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
|
||||
Some(Subcommand::Sign(cmd)) => cmd.run(),
|
||||
Some(Subcommand::Verify(cmd)) => cmd.run(),
|
||||
@@ -94,79 +94,99 @@ pub fn run() -> sc_cli::Result<()> {
|
||||
Some(Subcommand::BuildSpec(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
|
||||
}
|
||||
},
|
||||
Some(Subcommand::CheckBlock(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents {
|
||||
client,
|
||||
task_manager,
|
||||
import_queue,
|
||||
..
|
||||
} = new_partial(&config)?;
|
||||
runner.async_run(|mut config| {
|
||||
let PartialComponents { client, task_manager, import_queue, .. } =
|
||||
new_partial(&mut config).map_err(service_error)?;
|
||||
Ok((cmd.run(client, import_queue), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ExportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents {
|
||||
client, task_manager, ..
|
||||
} = new_partial(&config)?;
|
||||
runner.async_run(|mut config| {
|
||||
let PartialComponents { client, task_manager, .. } =
|
||||
new_partial(&mut config).map_err(service_error)?;
|
||||
Ok((cmd.run(client, config.database), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ExportState(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents {
|
||||
client, task_manager, ..
|
||||
} = new_partial(&config)?;
|
||||
runner.async_run(|mut config| {
|
||||
let PartialComponents { client, task_manager, .. } =
|
||||
new_partial(&mut config).map_err(service_error)?;
|
||||
Ok((cmd.run(client, config.chain_spec), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ImportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents {
|
||||
client,
|
||||
task_manager,
|
||||
import_queue,
|
||||
..
|
||||
} = new_partial(&config)?;
|
||||
runner.async_run(|mut config| {
|
||||
let PartialComponents { client, task_manager, import_queue, .. } =
|
||||
new_partial(&mut config).map_err(service_error)?;
|
||||
Ok((cmd.run(client, import_queue), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::PurgeChain(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run(config.database))
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Revert(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents {
|
||||
client,
|
||||
task_manager,
|
||||
backend,
|
||||
..
|
||||
} = new_partial(&config)?;
|
||||
runner.async_run(|mut config| {
|
||||
let PartialComponents { client, task_manager, backend, .. } =
|
||||
new_partial(&mut config).map_err(service_error)?;
|
||||
Ok((cmd.run(client, backend), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Inspect(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run::<Block, RuntimeApi, service::Executor>(config))
|
||||
}
|
||||
runner.sync_run(|config| {
|
||||
cmd.run::<Block, RuntimeApi, crate::service::ExecutorDispatch>(config)
|
||||
})
|
||||
},
|
||||
Some(Subcommand::PvfPrepareWorker(cmd)) => {
|
||||
let mut builder = sc_cli::LoggerBuilder::new("");
|
||||
builder.with_colors(false);
|
||||
let _ = builder.init();
|
||||
|
||||
polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path);
|
||||
Ok(())
|
||||
},
|
||||
Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => {
|
||||
let mut builder = sc_cli::LoggerBuilder::new("");
|
||||
builder.with_colors(false);
|
||||
let _ = builder.init();
|
||||
|
||||
polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path);
|
||||
Ok(())
|
||||
},
|
||||
None => {
|
||||
let runner = cli.create_runner(&cli.run)?;
|
||||
runner
|
||||
.run_node_until_exit(|config| async move {
|
||||
match config.role {
|
||||
Role::Light => service::new_light(config),
|
||||
_ => service::new_full(config),
|
||||
}
|
||||
})
|
||||
.map_err(sc_cli::Error::Service)
|
||||
}
|
||||
|
||||
// some parameters that are used by polkadot nodes, but that are not used by our binary
|
||||
// let jaeger_agent = None;
|
||||
// let grandpa_pause = None;
|
||||
// let no_beefy = true;
|
||||
// let telemetry_worker_handler = None;
|
||||
// let is_collator = crate::service::IsCollator::No;
|
||||
let overseer_gen = crate::overseer::RealOverseerGen;
|
||||
runner.run_node_until_exit(|config| async move {
|
||||
match config.role {
|
||||
Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other(
|
||||
"Light client is not supported by this node".into(),
|
||||
))),
|
||||
_ => crate::service::build_full(config, overseer_gen)
|
||||
.map(|full| full.task_manager)
|
||||
.map_err(service_error),
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to change 'service.rs' too much to ease future updates => it'll keep using
|
||||
// its own error enum like original polkadot service does.
|
||||
fn service_error(err: crate::service::Error) -> sc_cli::Error {
|
||||
sc_cli::Error::Application(Box::new(err))
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ mod chain_spec;
|
||||
mod service;
|
||||
mod cli;
|
||||
mod command;
|
||||
mod overseer;
|
||||
mod parachains_db;
|
||||
|
||||
/// Run the Rialto Node
|
||||
fn main() -> sc_cli::Result<()> {
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
// Copyright 2019-2021 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 almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository.
|
||||
//! The only exception is that we don't support db upgrades => no `upgrade.rs` module.
|
||||
|
||||
// this warning comes from `polkadot_overseer::AllSubsystems` type
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use crate::service::{AuthorityDiscoveryApi, Error};
|
||||
use rialto_runtime::{opaque::Block, Hash};
|
||||
|
||||
use lru::LruCache;
|
||||
use polkadot_availability_distribution::IncomingRequestReceivers;
|
||||
use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
|
||||
use polkadot_node_core_av_store::Config as AvailabilityConfig;
|
||||
use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
|
||||
use polkadot_node_core_chain_selection::Config as ChainSelectionConfig;
|
||||
use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
|
||||
use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver};
|
||||
use polkadot_overseer::{
|
||||
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder,
|
||||
OverseerConnector, OverseerHandle,
|
||||
};
|
||||
use polkadot_primitives::v1::ParachainHost;
|
||||
use sc_authority_discovery::Service as AuthorityDiscoveryService;
|
||||
use sc_client_api::AuxStore;
|
||||
use sc_keystore::LocalKeystore;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_consensus_babe::BabeApi;
|
||||
use sp_core::traits::SpawnNamed;
|
||||
use std::sync::Arc;
|
||||
use substrate_prometheus_endpoint::Registry;
|
||||
|
||||
pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
|
||||
pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem;
|
||||
pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem;
|
||||
pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
|
||||
pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide};
|
||||
pub use polkadot_dispute_distribution::DisputeDistributionSubsystem;
|
||||
pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem;
|
||||
pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem;
|
||||
pub use polkadot_node_collation_generation::CollationGenerationSubsystem;
|
||||
pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem;
|
||||
pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem;
|
||||
pub use polkadot_node_core_backing::CandidateBackingSubsystem;
|
||||
pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem;
|
||||
pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem;
|
||||
pub use polkadot_node_core_chain_api::ChainApiSubsystem;
|
||||
pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem;
|
||||
pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem;
|
||||
pub use polkadot_node_core_provisioner::ProvisionerSubsystem;
|
||||
pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem;
|
||||
pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem;
|
||||
|
||||
/// Arguments passed for overseer construction.
|
||||
pub struct OverseerGenArgs<'a, Spawner, RuntimeClient>
|
||||
where
|
||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
|
||||
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Spawner: 'static + SpawnNamed + Clone + Unpin,
|
||||
{
|
||||
/// Set of initial relay chain leaves to track.
|
||||
pub leaves: Vec<BlockInfo>,
|
||||
/// The keystore to use for i.e. validator keys.
|
||||
pub keystore: Arc<LocalKeystore>,
|
||||
/// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others.
|
||||
pub runtime_client: Arc<RuntimeClient>,
|
||||
/// The underlying key value store for the parachains.
|
||||
pub parachains_db: Arc<dyn kvdb::KeyValueDB>,
|
||||
/// Underlying network service implementation.
|
||||
pub network_service: Arc<sc_network::NetworkService<Block, Hash>>,
|
||||
/// Underlying authority discovery service.
|
||||
pub authority_discovery_service: AuthorityDiscoveryService,
|
||||
/// POV request receiver
|
||||
pub pov_req_receiver: IncomingRequestReceiver<request_v1::PoVFetchingRequest>,
|
||||
pub chunk_req_receiver: IncomingRequestReceiver<request_v1::ChunkFetchingRequest>,
|
||||
pub collation_req_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>,
|
||||
pub available_data_req_receiver:
|
||||
IncomingRequestReceiver<request_v1::AvailableDataFetchingRequest>,
|
||||
pub statement_req_receiver: IncomingRequestReceiver<request_v1::StatementFetchingRequest>,
|
||||
pub dispute_req_receiver: IncomingRequestReceiver<request_v1::DisputeRequest>,
|
||||
/// Prometheus registry, commonly used for production systems, less so for test.
|
||||
pub registry: Option<&'a Registry>,
|
||||
/// Task spawner to be used throughout the overseer and the APIs it provides.
|
||||
pub spawner: Spawner,
|
||||
/// Configuration for the approval voting subsystem.
|
||||
pub approval_voting_config: ApprovalVotingConfig,
|
||||
/// Configuration for the availability store subsystem.
|
||||
pub availability_config: AvailabilityConfig,
|
||||
/// Configuration for the candidate validation subsystem.
|
||||
pub candidate_validation_config: CandidateValidationConfig,
|
||||
/// Configuration for the chain selection subsystem.
|
||||
pub chain_selection_config: ChainSelectionConfig,
|
||||
/// Configuration for the dispute coordinator subsystem.
|
||||
pub dispute_coordinator_config: DisputeCoordinatorConfig,
|
||||
}
|
||||
|
||||
/// Obtain a prepared `OverseerBuilder`, that is initialized
|
||||
/// with all default values.
|
||||
pub fn prepared_overseer_builder<Spawner, RuntimeClient>(
|
||||
OverseerGenArgs {
|
||||
leaves,
|
||||
keystore,
|
||||
runtime_client,
|
||||
parachains_db,
|
||||
network_service,
|
||||
authority_discovery_service,
|
||||
pov_req_receiver,
|
||||
chunk_req_receiver,
|
||||
collation_req_receiver: _,
|
||||
available_data_req_receiver,
|
||||
statement_req_receiver,
|
||||
dispute_req_receiver,
|
||||
registry,
|
||||
spawner,
|
||||
approval_voting_config,
|
||||
availability_config,
|
||||
candidate_validation_config,
|
||||
chain_selection_config,
|
||||
dispute_coordinator_config,
|
||||
}: OverseerGenArgs<'_, Spawner, RuntimeClient>,
|
||||
) -> Result<
|
||||
OverseerBuilder<
|
||||
Spawner,
|
||||
Arc<RuntimeClient>,
|
||||
CandidateValidationSubsystem,
|
||||
CandidateBackingSubsystem<Spawner>,
|
||||
StatementDistributionSubsystem,
|
||||
AvailabilityDistributionSubsystem,
|
||||
AvailabilityRecoverySubsystem,
|
||||
BitfieldSigningSubsystem<Spawner>,
|
||||
BitfieldDistributionSubsystem,
|
||||
ProvisionerSubsystem<Spawner>,
|
||||
RuntimeApiSubsystem<RuntimeClient>,
|
||||
AvailabilityStoreSubsystem,
|
||||
NetworkBridgeSubsystem<
|
||||
Arc<sc_network::NetworkService<Block, Hash>>,
|
||||
AuthorityDiscoveryService,
|
||||
>,
|
||||
ChainApiSubsystem<RuntimeClient>,
|
||||
CollationGenerationSubsystem,
|
||||
CollatorProtocolSubsystem,
|
||||
ApprovalDistributionSubsystem,
|
||||
ApprovalVotingSubsystem,
|
||||
GossipSupportSubsystem<AuthorityDiscoveryService>,
|
||||
DisputeCoordinatorSubsystem,
|
||||
DisputeDistributionSubsystem<AuthorityDiscoveryService>,
|
||||
ChainSelectionSubsystem,
|
||||
>,
|
||||
Error,
|
||||
>
|
||||
where
|
||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
|
||||
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Spawner: 'static + SpawnNamed + Clone + Unpin,
|
||||
{
|
||||
use polkadot_node_subsystem_util::metrics::Metrics;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
|
||||
|
||||
let builder = Overseer::builder()
|
||||
.availability_distribution(AvailabilityDistributionSubsystem::new(
|
||||
keystore.clone(),
|
||||
IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver },
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only(
|
||||
available_data_req_receiver,
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.availability_store(AvailabilityStoreSubsystem::new(
|
||||
parachains_db.clone(),
|
||||
availability_config,
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?))
|
||||
.bitfield_signing(BitfieldSigningSubsystem::new(
|
||||
spawner.clone(),
|
||||
keystore.clone(),
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.candidate_backing(CandidateBackingSubsystem::new(
|
||||
spawner.clone(),
|
||||
keystore.clone(),
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.candidate_validation(CandidateValidationSubsystem::with_config(
|
||||
candidate_validation_config,
|
||||
Metrics::register(registry)?, // candidate-validation metrics
|
||||
Metrics::register(registry)?, // validation host metrics
|
||||
))
|
||||
.chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
|
||||
.collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?))
|
||||
.collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator {
|
||||
keystore: keystore.clone(),
|
||||
eviction_policy: Default::default(),
|
||||
metrics: Metrics::register(registry)?,
|
||||
}))
|
||||
.network_bridge(NetworkBridgeSubsystem::new(
|
||||
network_service.clone(),
|
||||
authority_discovery_service.clone(),
|
||||
Box::new(network_service.clone()),
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?))
|
||||
.runtime_api(RuntimeApiSubsystem::new(
|
||||
runtime_client.clone(),
|
||||
Metrics::register(registry)?,
|
||||
spawner.clone(),
|
||||
))
|
||||
.statement_distribution(StatementDistributionSubsystem::new(
|
||||
keystore.clone(),
|
||||
statement_req_receiver,
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?))
|
||||
.approval_voting(ApprovalVotingSubsystem::with_config(
|
||||
approval_voting_config,
|
||||
parachains_db.clone(),
|
||||
keystore.clone(),
|
||||
Box::new(network_service),
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.gossip_support(GossipSupportSubsystem::new(
|
||||
keystore.clone(),
|
||||
authority_discovery_service.clone(),
|
||||
))
|
||||
.dispute_coordinator(DisputeCoordinatorSubsystem::new(
|
||||
parachains_db.clone(),
|
||||
dispute_coordinator_config,
|
||||
keystore.clone(),
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.dispute_distribution(DisputeDistributionSubsystem::new(
|
||||
keystore,
|
||||
dispute_req_receiver,
|
||||
authority_discovery_service,
|
||||
Metrics::register(registry)?,
|
||||
))
|
||||
.chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db))
|
||||
.leaves(Vec::from_iter(
|
||||
leaves
|
||||
.into_iter()
|
||||
.map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)),
|
||||
))
|
||||
.activation_external_listeners(Default::default())
|
||||
.span_per_active_leaf(Default::default())
|
||||
.active_leaves(Default::default())
|
||||
.supports_parachains(runtime_client)
|
||||
.known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE))
|
||||
.metrics(metrics)
|
||||
.spawner(spawner);
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
/// Trait for the `fn` generating the overseer.
|
||||
///
|
||||
/// Default behavior is to create an unmodified overseer, as `RealOverseerGen`
|
||||
/// would do.
|
||||
pub trait OverseerGen {
|
||||
/// Overwrite the full generation of the overseer, including the subsystems.
|
||||
fn generate<Spawner, RuntimeClient>(
|
||||
&self,
|
||||
connector: OverseerConnector,
|
||||
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
|
||||
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
|
||||
where
|
||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
|
||||
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Spawner: 'static + SpawnNamed + Clone + Unpin,
|
||||
{
|
||||
let gen = RealOverseerGen;
|
||||
RealOverseerGen::generate::<Spawner, RuntimeClient>(&gen, connector, args)
|
||||
}
|
||||
// It would be nice to make `create_subsystems` part of this trait,
|
||||
// but the amount of generic arguments that would be required as
|
||||
// as consequence make this rather annoying to implement and use.
|
||||
}
|
||||
|
||||
use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE;
|
||||
|
||||
/// The regular set of subsystems.
|
||||
pub struct RealOverseerGen;
|
||||
|
||||
impl OverseerGen for RealOverseerGen {
|
||||
fn generate<Spawner, RuntimeClient>(
|
||||
&self,
|
||||
connector: OverseerConnector,
|
||||
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
|
||||
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
|
||||
where
|
||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
|
||||
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Spawner: 'static + SpawnNamed + Clone + Unpin,
|
||||
{
|
||||
prepared_overseer_builder(args)?
|
||||
.build_with_connector(connector)
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright 2019-2021 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 almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository.
|
||||
//! The only exception is that we don't support db upgrades => no `upgrade.rs` module.
|
||||
|
||||
use kvdb::KeyValueDB;
|
||||
use std::{io, path::PathBuf, sync::Arc};
|
||||
|
||||
mod columns {
|
||||
pub const NUM_COLUMNS: u32 = 5;
|
||||
|
||||
pub const COL_AVAILABILITY_DATA: u32 = 0;
|
||||
pub const COL_AVAILABILITY_META: u32 = 1;
|
||||
pub const COL_APPROVAL_DATA: u32 = 2;
|
||||
pub const COL_CHAIN_SELECTION_DATA: u32 = 3;
|
||||
pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4;
|
||||
}
|
||||
|
||||
/// Columns used by different subsystems.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ColumnsConfig {
|
||||
/// The column used by the av-store for data.
|
||||
pub col_availability_data: u32,
|
||||
/// The column used by the av-store for meta information.
|
||||
pub col_availability_meta: u32,
|
||||
/// The column used by approval voting for data.
|
||||
pub col_approval_data: u32,
|
||||
/// The column used by chain selection for data.
|
||||
pub col_chain_selection_data: u32,
|
||||
/// The column used by dispute coordinator for data.
|
||||
pub col_dispute_coordinator_data: u32,
|
||||
}
|
||||
|
||||
/// The real columns used by the parachains DB.
|
||||
pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig {
|
||||
col_availability_data: columns::COL_AVAILABILITY_DATA,
|
||||
col_availability_meta: columns::COL_AVAILABILITY_META,
|
||||
col_approval_data: columns::COL_APPROVAL_DATA,
|
||||
col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA,
|
||||
col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA,
|
||||
};
|
||||
|
||||
/// The cache size for each column, in megabytes.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CacheSizes {
|
||||
/// Cache used by availability data.
|
||||
pub availability_data: usize,
|
||||
/// Cache used by availability meta.
|
||||
pub availability_meta: usize,
|
||||
/// Cache used by approval data.
|
||||
pub approval_data: usize,
|
||||
}
|
||||
|
||||
impl Default for CacheSizes {
|
||||
fn default() -> Self {
|
||||
CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 }
|
||||
}
|
||||
}
|
||||
|
||||
fn other_io_error(err: String) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, err)
|
||||
}
|
||||
|
||||
/// Open the database on disk, creating it if it doesn't exist.
|
||||
pub fn open_creating(root: PathBuf, cache_sizes: CacheSizes) -> io::Result<Arc<dyn KeyValueDB>> {
|
||||
use kvdb_rocksdb::{Database, DatabaseConfig};
|
||||
|
||||
let path = root.join("parachains").join("db");
|
||||
|
||||
let mut db_config = DatabaseConfig::with_columns(columns::NUM_COLUMNS);
|
||||
|
||||
let _ = db_config
|
||||
.memory_budget
|
||||
.insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data);
|
||||
let _ = db_config
|
||||
.memory_budget
|
||||
.insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta);
|
||||
let _ = db_config
|
||||
.memory_budget
|
||||
.insert(columns::COL_APPROVAL_DATA, cache_sizes.approval_data);
|
||||
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?;
|
||||
|
||||
std::fs::create_dir_all(&path_str)?;
|
||||
let db = Database::open(&db_config, path_str)?;
|
||||
|
||||
Ok(Arc::new(db))
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,16 +8,15 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
||||
codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] }
|
||||
hex-literal = "0.3"
|
||||
libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] }
|
||||
libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
serde = { version = "1.0.124", optional = true, features = ["derive"] }
|
||||
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-currency-exchange = { path = "../../../primitives/currency-exchange", default-features = false }
|
||||
bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false }
|
||||
bp-header-chain = { path = "../../../primitives/header-chain", default-features = false }
|
||||
bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false }
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
@@ -25,47 +24,56 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals
|
||||
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
|
||||
pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false }
|
||||
pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false }
|
||||
pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
|
||||
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
|
||||
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
|
||||
# Polkadot (parachain) Dependencies
|
||||
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
|
||||
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
|
||||
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
libsecp256k1 = { version = "0.3.4", features = ["hmac"] }
|
||||
libsecp256k1 = { version = "0.7", features = ["hmac"] }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
@@ -73,8 +81,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-currency-exchange/std",
|
||||
"bp-eth-poa/std",
|
||||
"beefy-primitives/std",
|
||||
"bp-header-chain/std",
|
||||
"bp-message-dispatch/std",
|
||||
"bp-messages/std",
|
||||
@@ -89,24 +96,31 @@ std = [
|
||||
"frame-system-rpc-runtime-api/std",
|
||||
"frame-system/std",
|
||||
"log/std",
|
||||
"pallet-aura/std",
|
||||
"pallet-authority-discovery/std",
|
||||
"pallet-babe/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-bridge-currency-exchange/std",
|
||||
"pallet-beefy/std",
|
||||
"pallet-beefy-mmr/std",
|
||||
"pallet-bridge-dispatch/std",
|
||||
"pallet-bridge-eth-poa/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-grandpa/std",
|
||||
"pallet-randomness-collective-flip/std",
|
||||
"pallet-mmr/std",
|
||||
"pallet-mmr-primitives/std",
|
||||
"pallet-shift-session-manager/std",
|
||||
"pallet-sudo/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-transaction-payment-rpc-runtime-api/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"polkadot-primitives/std",
|
||||
"polkadot-runtime-common/std",
|
||||
"polkadot-runtime-parachains/std",
|
||||
"scale-info/std",
|
||||
"serde",
|
||||
"sp-api/std",
|
||||
"sp-authority-discovery/std",
|
||||
"sp-block-builder/std",
|
||||
"sp-consensus-aura/std",
|
||||
"sp-consensus-babe/std",
|
||||
"sp-core/std",
|
||||
"sp-finality-grandpa/std",
|
||||
"sp-inherents/std",
|
||||
@@ -125,8 +139,6 @@ runtime-benchmarks = [
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"libsecp256k1",
|
||||
"pallet-bridge-currency-exchange/runtime-benchmarks",
|
||||
"pallet-bridge-eth-poa/runtime-benchmarks",
|
||||
"pallet-bridge-messages/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
]
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2020-2021 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/>.
|
||||
|
||||
//! We want to use a different validator configuration for benchmarking than what's used in Kovan
|
||||
//! or in our Rialto test network. However, we can't configure a new validator set on the fly which
|
||||
//! means we need to wire the runtime together like this
|
||||
|
||||
use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource};
|
||||
use sp_std::vec;
|
||||
|
||||
pub use crate::kovan::{
|
||||
genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy,
|
||||
};
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub BridgeValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config();
|
||||
}
|
||||
|
||||
fn bench_validator_config() -> ValidatorsConfiguration {
|
||||
ValidatorsConfiguration::Multi(vec![
|
||||
(0, ValidatorsSource::List(vec![[1; 20].into()])),
|
||||
(1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])),
|
||||
])
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Support for PoA -> Substrate native tokens exchange.
|
||||
//!
|
||||
//! If you want to exchange native PoA tokens for native Substrate
|
||||
//! chain tokens, you need to:
|
||||
//! 1) send some PoA tokens to `LOCK_FUNDS_ADDRESS` address on PoA chain. Data field of
|
||||
//! the transaction must be SCALE-encoded id of Substrate account that will receive
|
||||
//! funds on Substrate chain;
|
||||
//! 2) wait until the 'lock funds' transaction is mined on PoA chain;
|
||||
//! 3) wait until the block containing the 'lock funds' transaction is finalized on PoA chain;
|
||||
//! 4) wait until the required PoA header and its finality are provided
|
||||
//! to the PoA -> Substrate bridge module (it can be provided by you);
|
||||
//! 5) receive tokens by providing proof-of-inclusion of PoA transaction.
|
||||
|
||||
use bp_currency_exchange::{
|
||||
Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult,
|
||||
};
|
||||
use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::RuntimeDebug;
|
||||
use hex_literal::hex;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
/// Ethereum address where locked PoA funds must be sent to.
|
||||
pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
|
||||
|
||||
/// Ethereum transaction inclusion proof.
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)]
|
||||
pub struct EthereumTransactionInclusionProof {
|
||||
/// Hash of the block with transaction.
|
||||
pub block: sp_core::H256,
|
||||
/// Index of the transaction within the block.
|
||||
pub index: u64,
|
||||
/// The proof itself (right now it is all RLP-encoded transactions of the block +
|
||||
/// RLP-encoded receipts of all transactions of the block).
|
||||
pub proof: Vec<(RawTransaction, RawTransactionReceipt)>,
|
||||
}
|
||||
|
||||
/// We uniquely identify transfer by the pair (sender, nonce).
|
||||
///
|
||||
/// The assumption is that this pair will never appear more than once in
|
||||
/// transactions included into finalized blocks. This is obviously true
|
||||
/// for any existing eth-like chain (that keep current transaction format),
|
||||
/// because otherwise transaction can be replayed over and over.
|
||||
#[derive(Encode, Decode, PartialEq, RuntimeDebug)]
|
||||
pub struct EthereumTransactionTag {
|
||||
/// Account that has locked funds.
|
||||
pub account: [u8; 20],
|
||||
/// Lock transaction nonce.
|
||||
pub nonce: sp_core::U256,
|
||||
}
|
||||
|
||||
/// Eth transaction from runtime perspective.
|
||||
pub struct EthTransaction;
|
||||
|
||||
impl MaybeLockFundsTransaction for EthTransaction {
|
||||
type Transaction = RawTransaction;
|
||||
type Id = EthereumTransactionTag;
|
||||
type Recipient = crate::AccountId;
|
||||
type Amount = crate::Balance;
|
||||
|
||||
fn parse(
|
||||
raw_tx: &Self::Transaction,
|
||||
) -> ExchangeResult<LockFundsTransaction<Self::Id, Self::Recipient, Self::Amount>> {
|
||||
let tx = transaction_decode_rlp(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?;
|
||||
|
||||
// we only accept transactions sending funds directly to the pre-configured address
|
||||
if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) {
|
||||
log::trace!(
|
||||
target: "runtime",
|
||||
"Failed to parse fund locks transaction. Invalid peer recipient: {:?}",
|
||||
tx.unsigned.to,
|
||||
);
|
||||
|
||||
return Err(ExchangeError::InvalidTransaction);
|
||||
}
|
||||
|
||||
let mut recipient_raw = sp_core::H256::default();
|
||||
match tx.unsigned.payload.len() {
|
||||
32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload),
|
||||
len => {
|
||||
log::trace!(
|
||||
target: "runtime",
|
||||
"Failed to parse fund locks transaction. Invalid recipient length: {}",
|
||||
len,
|
||||
);
|
||||
|
||||
return Err(ExchangeError::InvalidRecipient);
|
||||
}
|
||||
}
|
||||
let amount = tx.unsigned.value.low_u128();
|
||||
|
||||
if tx.unsigned.value != amount.into() {
|
||||
log::trace!(
|
||||
target: "runtime",
|
||||
"Failed to parse fund locks transaction. Invalid amount: {}",
|
||||
tx.unsigned.value,
|
||||
);
|
||||
|
||||
return Err(ExchangeError::InvalidAmount);
|
||||
}
|
||||
|
||||
Ok(LockFundsTransaction {
|
||||
id: EthereumTransactionTag {
|
||||
account: *tx.sender.as_fixed_bytes(),
|
||||
nonce: tx.unsigned.nonce,
|
||||
},
|
||||
recipient: crate::AccountId::from(*recipient_raw.as_fixed_bytes()),
|
||||
amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares everything required to bench claim of funds locked by given transaction.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: frame_support::traits::Instance>(
|
||||
transactions: &[(RawTransaction, RawTransactionReceipt)],
|
||||
) -> bp_eth_poa::H256 {
|
||||
use bp_eth_poa::compute_merkle_root;
|
||||
use pallet_bridge_eth_poa::{
|
||||
test_utils::{insert_dummy_header, validator_utils::validator, HeaderBuilder},
|
||||
BridgeStorage, Storage,
|
||||
};
|
||||
|
||||
let mut storage = BridgeStorage::<T, I>::new();
|
||||
let header = HeaderBuilder::with_parent_number_on_runtime::<T, I>(0)
|
||||
.transactions_root(compute_merkle_root(transactions.iter().map(|(tx, _)| tx)))
|
||||
.receipts_root(compute_merkle_root(transactions.iter().map(|(_, receipt)| receipt)))
|
||||
.sign_by(&validator(0));
|
||||
let header_id = header.compute_id();
|
||||
insert_dummy_header(&mut storage, header);
|
||||
storage.finalize_and_prune_headers(Some(header_id), 0);
|
||||
|
||||
header_id.hash
|
||||
}
|
||||
|
||||
/// Prepare signed ethereum lock-funds transaction.
|
||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||
pub(crate) fn prepare_ethereum_transaction(
|
||||
recipient: &crate::AccountId,
|
||||
editor: impl Fn(&mut bp_eth_poa::UnsignedTransaction),
|
||||
) -> (RawTransaction, RawTransactionReceipt) {
|
||||
use bp_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome};
|
||||
|
||||
// prepare tx for OpenEthereum private dev chain:
|
||||
// chain id is 0x11
|
||||
// sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7
|
||||
let chain_id = 0x11;
|
||||
let signer = secp256k1::SecretKey::parse(&hex!(
|
||||
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"
|
||||
))
|
||||
.unwrap();
|
||||
let recipient_raw: &[u8; 32] = recipient.as_ref();
|
||||
let mut eth_tx = bp_eth_poa::UnsignedTransaction {
|
||||
nonce: 0.into(),
|
||||
to: Some(LOCK_FUNDS_ADDRESS.into()),
|
||||
value: 100.into(),
|
||||
gas: 100_000.into(),
|
||||
gas_price: 100_000.into(),
|
||||
payload: recipient_raw.to_vec(),
|
||||
};
|
||||
editor(&mut eth_tx);
|
||||
(
|
||||
eth_tx.sign_by(&signer, Some(chain_id)),
|
||||
Receipt {
|
||||
outcome: TransactionOutcome::StatusCode(1),
|
||||
gas_used: Default::default(),
|
||||
log_bloom: Default::default(),
|
||||
logs: Vec::new(),
|
||||
}
|
||||
.rlp(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use hex_literal::hex;
|
||||
|
||||
fn ferdie() -> crate::AccountId {
|
||||
hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_transaction_accepted() {
|
||||
assert_eq!(
|
||||
EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {}).0),
|
||||
Ok(LockFundsTransaction {
|
||||
id: EthereumTransactionTag {
|
||||
account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"),
|
||||
nonce: 0.into(),
|
||||
},
|
||||
recipient: ferdie(),
|
||||
amount: 100,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_transaction_rejected() {
|
||||
assert_eq!(
|
||||
EthTransaction::parse(&Vec::new()),
|
||||
Err(ExchangeError::InvalidTransaction),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transaction_with_invalid_peer_recipient_rejected() {
|
||||
assert_eq!(
|
||||
EthTransaction::parse(
|
||||
&prepare_ethereum_transaction(&ferdie(), |tx| {
|
||||
tx.to = None;
|
||||
})
|
||||
.0
|
||||
),
|
||||
Err(ExchangeError::InvalidTransaction),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transaction_with_invalid_recipient_rejected() {
|
||||
assert_eq!(
|
||||
EthTransaction::parse(
|
||||
&prepare_ethereum_transaction(&ferdie(), |tx| {
|
||||
tx.payload.clear();
|
||||
})
|
||||
.0
|
||||
),
|
||||
Err(ExchangeError::InvalidRecipient),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transaction_with_invalid_amount_rejected() {
|
||||
assert_eq!(
|
||||
EthTransaction::parse(
|
||||
&prepare_ethereum_transaction(&ferdie(), |tx| {
|
||||
tx.value = sp_core::U256::from(u128::MAX) + sp_core::U256::from(1);
|
||||
})
|
||||
.0
|
||||
),
|
||||
Err(ExchangeError::InvalidAmount),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::exchange::EthereumTransactionInclusionProof;
|
||||
|
||||
use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256};
|
||||
use bp_header_chain::InclusionProofVerifier;
|
||||
use frame_support::RuntimeDebug;
|
||||
use hex_literal::hex;
|
||||
use pallet_bridge_eth_poa::{
|
||||
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration,
|
||||
ValidatorsSource,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub const FinalityVotesCachingInterval: Option<u64> = Some(16);
|
||||
pub BridgeAuraConfiguration: AuraConfiguration =
|
||||
kovan_aura_configuration();
|
||||
pub BridgeValidatorsConfiguration: ValidatorsConfiguration =
|
||||
kovan_validators_configuration();
|
||||
}
|
||||
|
||||
/// Max number of finalized headers to keep. It is equivalent of approximately
|
||||
/// 24 hours of finalized blocks on current Kovan chain.
|
||||
const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000;
|
||||
|
||||
/// Aura engine configuration for Kovan chain.
|
||||
pub fn kovan_aura_configuration() -> AuraConfiguration {
|
||||
AuraConfiguration {
|
||||
empty_steps_transition: u64::MAX,
|
||||
strict_empty_steps_transition: 0,
|
||||
validate_step_transition: 0x16e360,
|
||||
validate_score_transition: 0x41a3c4,
|
||||
two_thirds_majority_transition: u64::MAX,
|
||||
min_gas_limit: 0x1388.into(),
|
||||
max_gas_limit: U256::MAX,
|
||||
maximum_extra_data_size: 0x20,
|
||||
}
|
||||
}
|
||||
|
||||
/// Validators configuration for Kovan chain.
|
||||
pub fn kovan_validators_configuration() -> ValidatorsConfiguration {
|
||||
ValidatorsConfiguration::Multi(vec![
|
||||
(0, ValidatorsSource::List(genesis_validators())),
|
||||
(
|
||||
10960440,
|
||||
ValidatorsSource::List(vec![
|
||||
hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(),
|
||||
hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(),
|
||||
hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(),
|
||||
]),
|
||||
),
|
||||
(
|
||||
10960500,
|
||||
ValidatorsSource::Contract(
|
||||
hex!("aE71807C1B0a093cB1547b682DC78316D945c9B8").into(),
|
||||
vec![
|
||||
hex!("d05f7478c6aa10781258c5cc8b4f385fc8fa989c").into(),
|
||||
hex!("03801efb0efe2a25ede5dd3a003ae880c0292e4d").into(),
|
||||
hex!("a4df255ecf08bbf2c28055c65225c9a9847abd94").into(),
|
||||
hex!("596e8221a30bfe6e7eff67fee664a01c73ba3c56").into(),
|
||||
hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(),
|
||||
],
|
||||
),
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
/// Genesis validators set of Kovan chain.
|
||||
pub fn genesis_validators() -> Vec<Address> {
|
||||
vec![
|
||||
hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(),
|
||||
hex!("00427feae2419c15b89d1c21af10d1b6650a4d3d").into(),
|
||||
hex!("4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c").into(),
|
||||
hex!("0020ee4Be0e2027d76603cB751eE069519bA81A1").into(),
|
||||
hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(),
|
||||
hex!("007733a1FE69CF3f2CF989F81C7b4cAc1693387A").into(),
|
||||
hex!("00E6d2b931F55a3f1701c7389d592a7778897879").into(),
|
||||
hex!("00e4a10650e5a6D6001C38ff8E64F97016a1645c").into(),
|
||||
hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Genesis header of the Kovan chain.
|
||||
pub fn genesis_header() -> AuraHeader {
|
||||
AuraHeader {
|
||||
parent_hash: Default::default(),
|
||||
timestamp: 0,
|
||||
number: 0,
|
||||
author: Default::default(),
|
||||
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
|
||||
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
|
||||
extra_data: vec![],
|
||||
state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(),
|
||||
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
|
||||
log_bloom: Default::default(),
|
||||
gas_used: Default::default(),
|
||||
gas_limit: 6000000.into(),
|
||||
difficulty: 131072.into(),
|
||||
seal: vec![
|
||||
vec![128],
|
||||
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,
|
||||
],
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/// Kovan headers pruning strategy.
|
||||
///
|
||||
/// We do not prune unfinalized headers because exchange module only accepts
|
||||
/// claims from finalized headers. And if we're pruning unfinalized headers, then
|
||||
/// some claims may never be accepted.
|
||||
#[derive(Default, RuntimeDebug)]
|
||||
pub struct PruningStrategy;
|
||||
|
||||
impl BridgePruningStrategy for PruningStrategy {
|
||||
fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 {
|
||||
best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP)
|
||||
}
|
||||
}
|
||||
|
||||
/// PoA Header timestamp verification against `Timestamp` pallet.
|
||||
#[derive(Default, RuntimeDebug)]
|
||||
pub struct ChainTime;
|
||||
|
||||
impl TChainTime for ChainTime {
|
||||
fn is_timestamp_ahead(&self, timestamp: u64) -> bool {
|
||||
let now = super::Timestamp::now();
|
||||
timestamp > now
|
||||
}
|
||||
}
|
||||
|
||||
/// The Kovan Blockchain as seen by the runtime.
|
||||
pub struct KovanBlockchain;
|
||||
|
||||
impl InclusionProofVerifier for KovanBlockchain {
|
||||
type Transaction = RawTransaction;
|
||||
type TransactionInclusionProof = EthereumTransactionInclusionProof;
|
||||
|
||||
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> {
|
||||
let is_transaction_finalized =
|
||||
crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof);
|
||||
|
||||
if !is_transaction_finalized {
|
||||
return None;
|
||||
}
|
||||
|
||||
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pruning_strategy_keeps_enough_headers() {
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 10_000),
|
||||
0,
|
||||
"10_000 <= 20_000 => nothing should be pruned yet",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 20_000),
|
||||
0,
|
||||
"20_000 <= 20_000 => nothing should be pruned yet",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 30_000),
|
||||
10_000,
|
||||
"20_000 <= 30_000 => we're ready to prune first 10_000 headers",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -30,34 +30,32 @@
|
||||
#[cfg(feature = "std")]
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
pub mod exchange;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub mod benches;
|
||||
pub mod kovan;
|
||||
pub mod millau_messages;
|
||||
pub mod rialto_poa;
|
||||
pub mod parachains;
|
||||
|
||||
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
||||
|
||||
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
|
||||
use bridge_runtime_common::messages::{
|
||||
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
|
||||
};
|
||||
use codec::Decode;
|
||||
use pallet_grandpa::{
|
||||
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
||||
};
|
||||
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
|
||||
use pallet_mmr_primitives::{
|
||||
DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof,
|
||||
};
|
||||
use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
|
||||
use sp_api::impl_runtime_apis;
|
||||
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys,
|
||||
traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys},
|
||||
traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult, MultiSignature, MultiSigner,
|
||||
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
|
||||
#[cfg(feature = "std")]
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
@@ -72,8 +70,6 @@ pub use frame_support::{
|
||||
|
||||
pub use frame_system::Call as SystemCall;
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall;
|
||||
pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall;
|
||||
pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall;
|
||||
pub use pallet_bridge_messages::Call as MessagesCall;
|
||||
pub use pallet_sudo::Call as SudoCall;
|
||||
@@ -101,7 +97,7 @@ pub type AccountIndex = u32;
|
||||
pub type Balance = bp_rialto::Balance;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Index = u32;
|
||||
pub type Index = bp_rialto::Index;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = bp_rialto::Hash;
|
||||
@@ -109,9 +105,6 @@ pub type Hash = bp_rialto::Hash;
|
||||
/// Hashing algorithm used by the chain.
|
||||
pub type Hashing = bp_rialto::Hasher;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = generic::DigestItem<Hash>;
|
||||
|
||||
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
||||
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
||||
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
||||
@@ -131,8 +124,12 @@ pub mod opaque {
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {
|
||||
pub aura: Aura,
|
||||
pub babe: Babe,
|
||||
pub grandpa: Grandpa,
|
||||
pub beefy: Beefy,
|
||||
pub para_validator: Initializer,
|
||||
pub para_assignment: SessionInfo,
|
||||
pub authority_discovery: AuthorityDiscovery,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +168,7 @@ impl frame_system::Config for Runtime {
|
||||
/// The aggregated dispatch type that is available for extrinsics.
|
||||
type Call = Call;
|
||||
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
|
||||
type Lookup = IdentityLookup<AccountId>;
|
||||
type Lookup = AccountIdLookup<AccountId, ()>;
|
||||
/// The index type for storing how many extrinsics an account has signed.
|
||||
type Index = Index;
|
||||
/// The index type for blocks.
|
||||
@@ -213,62 +210,50 @@ impl frame_system::Config for Runtime {
|
||||
type OnSetCode = ();
|
||||
}
|
||||
|
||||
impl pallet_randomness_collective_flip::Config for Runtime {}
|
||||
/// The BABE epoch configuration at genesis.
|
||||
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
|
||||
sp_consensus_babe::BabeEpochConfiguration {
|
||||
c: bp_rialto::time_units::PRIMARY_PROBABILITY,
|
||||
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots,
|
||||
};
|
||||
|
||||
parameter_types! {
|
||||
pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64;
|
||||
pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK;
|
||||
pub const MaxAuthorities: u32 = 10;
|
||||
}
|
||||
|
||||
impl pallet_aura::Config for Runtime {
|
||||
type AuthorityId = AuraId;
|
||||
impl pallet_babe::Config for Runtime {
|
||||
type EpochDuration = EpochDuration;
|
||||
type ExpectedBlockTime = ExpectedBlockTime;
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
|
||||
// session module is the trigger
|
||||
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
||||
|
||||
// equivocation related configuration - we don't expect any equivocations in our testnets
|
||||
type KeyOwnerProofSystem = ();
|
||||
type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
|
||||
KeyTypeId,
|
||||
pallet_babe::AuthorityId,
|
||||
)>>::Proof;
|
||||
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
|
||||
KeyTypeId,
|
||||
pallet_babe::AuthorityId,
|
||||
)>>::IdentificationTuple;
|
||||
type HandleEquivocation = ();
|
||||
|
||||
type DisabledValidators = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
type RialtoPoA = pallet_bridge_eth_poa::Instance1;
|
||||
impl pallet_bridge_eth_poa::Config<RialtoPoA> for Runtime {
|
||||
type AuraConfiguration = rialto_poa::BridgeAuraConfiguration;
|
||||
type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval;
|
||||
type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration;
|
||||
type PruningStrategy = rialto_poa::PruningStrategy;
|
||||
type ChainTime = rialto_poa::ChainTime;
|
||||
type OnHeadersSubmitted = ();
|
||||
}
|
||||
|
||||
type Kovan = pallet_bridge_eth_poa::Instance2;
|
||||
impl pallet_bridge_eth_poa::Config<Kovan> for Runtime {
|
||||
type AuraConfiguration = kovan::BridgeAuraConfiguration;
|
||||
type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval;
|
||||
type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration;
|
||||
type PruningStrategy = kovan::PruningStrategy;
|
||||
type ChainTime = kovan::ChainTime;
|
||||
type OnHeadersSubmitted = ();
|
||||
}
|
||||
|
||||
type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1;
|
||||
impl pallet_bridge_currency_exchange::Config<RialtoCurrencyExchange> for Runtime {
|
||||
type OnTransactionSubmitted = ();
|
||||
type PeerBlockchain = rialto_poa::RialtoBlockchain;
|
||||
type PeerMaybeLockFundsTransaction = exchange::EthTransaction;
|
||||
type RecipientsMap = bp_currency_exchange::IdentityRecipients<AccountId>;
|
||||
type Amount = Balance;
|
||||
type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter<Balance>;
|
||||
type DepositInto = DepositInto;
|
||||
}
|
||||
|
||||
type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2;
|
||||
impl pallet_bridge_currency_exchange::Config<KovanCurrencyExchange> for Runtime {
|
||||
type OnTransactionSubmitted = ();
|
||||
type PeerBlockchain = kovan::KovanBlockchain;
|
||||
type PeerMaybeLockFundsTransaction = exchange::EthTransaction;
|
||||
type RecipientsMap = bp_currency_exchange::IdentityRecipients<AccountId>;
|
||||
type Amount = Balance;
|
||||
type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter<Balance>;
|
||||
type DepositInto = DepositInto;
|
||||
impl pallet_beefy::Config for Runtime {
|
||||
type BeefyId = BeefyId;
|
||||
}
|
||||
|
||||
impl pallet_bridge_dispatch::Config for Runtime {
|
||||
type Event = Event;
|
||||
type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
|
||||
type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
|
||||
type Call = Call;
|
||||
type CallFilter = frame_support::traits::Everything;
|
||||
type EncodedCall = crate::millau_messages::FromMillauEncodedCall;
|
||||
@@ -278,71 +263,10 @@ impl pallet_bridge_dispatch::Config for Runtime {
|
||||
type AccountIdConverter = bp_rialto::AccountIdConverter;
|
||||
}
|
||||
|
||||
pub struct DepositInto;
|
||||
|
||||
impl bp_currency_exchange::DepositInto for DepositInto {
|
||||
type Recipient = AccountId;
|
||||
type Amount = Balance;
|
||||
|
||||
fn deposit_into(
|
||||
recipient: Self::Recipient,
|
||||
amount: Self::Amount,
|
||||
) -> bp_currency_exchange::Result<()> {
|
||||
// let balances module make all checks for us (it won't allow depositing lower than existential
|
||||
// deposit, balance overflow, ...)
|
||||
let deposited = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||
&recipient, amount,
|
||||
);
|
||||
|
||||
// I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance`
|
||||
// on drop
|
||||
let deposited_amount = deposited.peek();
|
||||
drop(deposited);
|
||||
|
||||
// we have 3 cases here:
|
||||
// - deposited == amount: success
|
||||
// - deposited == 0: deposit has failed and no changes to storage were made
|
||||
// - deposited != 0: (should never happen in practice) deposit has been partially completed
|
||||
match deposited_amount {
|
||||
_ if deposited_amount == amount => {
|
||||
log::trace!(
|
||||
target: "runtime",
|
||||
"Deposited {} to {:?}",
|
||||
amount,
|
||||
recipient,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
},
|
||||
_ if deposited_amount == 0 => {
|
||||
log::error!(
|
||||
target: "runtime",
|
||||
"Deposit of {} to {:?} has failed",
|
||||
amount,
|
||||
recipient,
|
||||
);
|
||||
|
||||
Err(bp_currency_exchange::Error::DepositFailed)
|
||||
},
|
||||
_ => {
|
||||
log::error!(
|
||||
target: "runtime",
|
||||
"Deposit of {} to {:?} has partially competed. {} has been deposited",
|
||||
amount,
|
||||
recipient,
|
||||
deposited_amount,
|
||||
);
|
||||
|
||||
// we can't return DepositFailed error here, because storage changes were made
|
||||
Err(bp_currency_exchange::Error::DepositPartiallyFailed)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_grandpa::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Call = Call;
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
type KeyOwnerProofSystem = ();
|
||||
type KeyOwnerProof =
|
||||
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
|
||||
@@ -356,14 +280,46 @@ impl pallet_grandpa::Config for Runtime {
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
}
|
||||
|
||||
impl pallet_mmr::Config for Runtime {
|
||||
const INDEXING_PREFIX: &'static [u8] = b"mmr";
|
||||
type Hashing = Keccak256;
|
||||
type Hash = <Keccak256 as sp_runtime::traits::Hash>::Output;
|
||||
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
|
||||
type WeightInfo = ();
|
||||
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// Version of the produced MMR leaf.
|
||||
///
|
||||
/// The version consists of two parts;
|
||||
/// - `major` (3 bits)
|
||||
/// - `minor` (5 bits)
|
||||
///
|
||||
/// `major` should be updated only if decoding the previous MMR Leaf format from the payload
|
||||
/// is not possible (i.e. backward incompatible change).
|
||||
/// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE
|
||||
/// encoding does not prevent old leafs from being decoded.
|
||||
///
|
||||
/// Hence we expect `major` to be changed really rarely (think never).
|
||||
/// See [`MmrLeafVersion`] type documentation for more details.
|
||||
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
|
||||
}
|
||||
|
||||
impl pallet_beefy_mmr::Config for Runtime {
|
||||
type LeafVersion = LeafVersion;
|
||||
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
|
||||
type ParachainHeads = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const MinimumPeriod: u64 = bp_rialto::SLOT_DURATION / 2;
|
||||
}
|
||||
|
||||
impl pallet_timestamp::Config for Runtime {
|
||||
/// A timestamp: milliseconds since the Unix epoch.
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = Aura;
|
||||
/// A timestamp: milliseconds since the UNIX epoch.
|
||||
type Moment = bp_rialto::Moment;
|
||||
type OnTimestampSet = Babe;
|
||||
type MinimumPeriod = MinimumPeriod;
|
||||
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
|
||||
type WeightInfo = ();
|
||||
@@ -395,13 +351,25 @@ impl pallet_balances::Config for Runtime {
|
||||
parameter_types! {
|
||||
pub const TransactionBaseFee: Balance = 0;
|
||||
pub const TransactionByteFee: Balance = 1;
|
||||
pub const OperationalFeeMultiplier: u8 = 5;
|
||||
// values for following parameters are copied from polkadot repo, but it is fine
|
||||
// not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains
|
||||
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
|
||||
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000);
|
||||
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128);
|
||||
}
|
||||
|
||||
impl pallet_transaction_payment::Config for Runtime {
|
||||
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
type WeightToFee = IdentityFee<Balance>;
|
||||
type FeeMultiplierUpdate = ();
|
||||
type OperationalFeeMultiplier = OperationalFeeMultiplier;
|
||||
type WeightToFee = bp_rialto::WeightToFee;
|
||||
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
|
||||
Runtime,
|
||||
TargetBlockFullness,
|
||||
AdjustmentVariable,
|
||||
MinimumMultiplier,
|
||||
>;
|
||||
}
|
||||
|
||||
impl pallet_sudo::Config for Runtime {
|
||||
@@ -409,17 +377,12 @@ impl pallet_sudo::Config for Runtime {
|
||||
type Call = Call;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const Period: BlockNumber = bp_rialto::SESSION_LENGTH;
|
||||
pub const Offset: BlockNumber = 0;
|
||||
}
|
||||
|
||||
impl pallet_session::Config for Runtime {
|
||||
type Event = Event;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
type ValidatorIdOf = ();
|
||||
type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
|
||||
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
|
||||
type ShouldEndSession = Babe;
|
||||
type NextSessionRotation = Babe;
|
||||
type SessionManager = pallet_shift_session_manager::Pallet<Runtime>;
|
||||
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
||||
type Keys = SessionKeys;
|
||||
@@ -427,6 +390,10 @@ impl pallet_session::Config for Runtime {
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl pallet_authority_discovery::Config for Runtime {
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// This is a pretty unscientific cap.
|
||||
///
|
||||
@@ -475,10 +442,11 @@ parameter_types! {
|
||||
pub const GetDeliveryConfirmationTransactionFee: Balance =
|
||||
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
|
||||
pub const RootAccountForPayments: Option<AccountId> = None;
|
||||
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID;
|
||||
}
|
||||
|
||||
/// Instance of the messages pallet used to relay messages to/from Millau chain.
|
||||
pub type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance;
|
||||
pub type WithMillauMessagesInstance = ();
|
||||
|
||||
impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
||||
type Event = Event;
|
||||
@@ -502,14 +470,17 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
||||
type MessageDeliveryAndDispatchPayment =
|
||||
pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
|
||||
Runtime,
|
||||
(),
|
||||
pallet_balances::Pallet<Runtime>,
|
||||
GetDeliveryConfirmationTransactionFee,
|
||||
RootAccountForPayments,
|
||||
>;
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
type SourceHeaderChain = crate::millau_messages::Millau;
|
||||
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
|
||||
type BridgedChainId = BridgedChainId;
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
@@ -518,28 +489,55 @@ construct_runtime!(
|
||||
NodeBlock = opaque::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
BridgeRialtoPoa: pallet_bridge_eth_poa::<Instance1>::{Pallet, Call, Config, Storage, ValidateUnsigned},
|
||||
BridgeKovan: pallet_bridge_eth_poa::<Instance2>::{Pallet, Call, Config, Storage, ValidateUnsigned},
|
||||
BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::<Instance1>::{Pallet, Call},
|
||||
BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::<Instance2>::{Pallet, Call},
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
|
||||
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>},
|
||||
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
||||
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
|
||||
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
|
||||
// Must be before session.
|
||||
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
|
||||
|
||||
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
|
||||
Aura: pallet_aura::{Pallet, Config<T>},
|
||||
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
|
||||
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
|
||||
// Consensus support.
|
||||
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
|
||||
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
|
||||
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
|
||||
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
|
||||
|
||||
// BEEFY Bridges support.
|
||||
Beefy: pallet_beefy::{Pallet, Storage, Config<T>},
|
||||
Mmr: pallet_mmr::{Pallet, Storage},
|
||||
MmrLeaf: pallet_beefy_mmr::{Pallet, Storage},
|
||||
|
||||
// Millau bridge modules.
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
|
||||
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
|
||||
// Parachain modules.
|
||||
ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin},
|
||||
Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config<T>},
|
||||
Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage},
|
||||
Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event<T>},
|
||||
ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent},
|
||||
Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage},
|
||||
Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config},
|
||||
Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage},
|
||||
Dmp: polkadot_runtime_parachains::dmp::{Pallet, Call, Storage},
|
||||
Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event},
|
||||
Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event<T>, Config},
|
||||
SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage},
|
||||
|
||||
// Parachain Onboarding Pallets
|
||||
Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event<T>},
|
||||
Slots: polkadot_runtime_common::slots::{Pallet, Call, Storage, Event<T>},
|
||||
ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call},
|
||||
}
|
||||
);
|
||||
|
||||
/// The address format for describing accounts.
|
||||
pub type Address = AccountId;
|
||||
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, Hashing>;
|
||||
/// Block type as expected by this runtime.
|
||||
@@ -570,7 +568,7 @@ pub type Executive = frame_executive::Executive<
|
||||
Block,
|
||||
frame_system::ChainContext<Runtime>,
|
||||
Runtime,
|
||||
AllPalletsWithSystem,
|
||||
AllPallets,
|
||||
>;
|
||||
|
||||
impl_runtime_apis! {
|
||||
@@ -621,43 +619,42 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_eth_poa::RialtoPoAHeaderApi<Block> for Runtime {
|
||||
fn best_block() -> (u64, bp_eth_poa::H256) {
|
||||
let best_block = BridgeRialtoPoa::best_block();
|
||||
(best_block.number, best_block.hash)
|
||||
}
|
||||
|
||||
fn finalized_block() -> (u64, bp_eth_poa::H256) {
|
||||
let finalized_block = BridgeRialtoPoa::finalized_block();
|
||||
(finalized_block.number, finalized_block.hash)
|
||||
}
|
||||
|
||||
fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool {
|
||||
BridgeRialtoPoa::is_import_requires_receipts(header)
|
||||
}
|
||||
|
||||
fn is_known_block(hash: bp_eth_poa::H256) -> bool {
|
||||
BridgeRialtoPoa::is_known_block(hash)
|
||||
impl beefy_primitives::BeefyApi<Block> for Runtime {
|
||||
fn validator_set() -> ValidatorSet<BeefyId> {
|
||||
Beefy::validator_set()
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_eth_poa::KovanHeaderApi<Block> for Runtime {
|
||||
fn best_block() -> (u64, bp_eth_poa::H256) {
|
||||
let best_block = BridgeKovan::best_block();
|
||||
(best_block.number, best_block.hash)
|
||||
impl pallet_mmr_primitives::MmrApi<Block, Hash> for Runtime {
|
||||
fn generate_proof(leaf_index: u64)
|
||||
-> Result<(EncodableOpaqueLeaf, MmrProof<Hash>), MmrError>
|
||||
{
|
||||
Mmr::generate_proof(leaf_index)
|
||||
.map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof))
|
||||
}
|
||||
|
||||
fn finalized_block() -> (u64, bp_eth_poa::H256) {
|
||||
let finalized_block = BridgeKovan::finalized_block();
|
||||
(finalized_block.number, finalized_block.hash)
|
||||
fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof<Hash>)
|
||||
-> Result<(), MmrError>
|
||||
{
|
||||
pub type Leaf = <
|
||||
<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider
|
||||
>::LeafData;
|
||||
|
||||
let leaf: Leaf = leaf
|
||||
.into_opaque_leaf()
|
||||
.try_decode()
|
||||
.ok_or(MmrError::Verify)?;
|
||||
Mmr::verify_leaf(leaf, proof)
|
||||
}
|
||||
|
||||
fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool {
|
||||
BridgeKovan::is_import_requires_receipts(header)
|
||||
}
|
||||
|
||||
fn is_known_block(hash: bp_eth_poa::H256) -> bool {
|
||||
BridgeKovan::is_known_block(hash)
|
||||
fn verify_proof_stateless(
|
||||
root: Hash,
|
||||
leaf: EncodableOpaqueLeaf,
|
||||
proof: MmrProof<Hash>
|
||||
) -> Result<(), MmrError> {
|
||||
type MmrHashing = <Runtime as pallet_mmr::Config>::Hashing;
|
||||
let node = DataOrHash::Data(leaf.into_opaque_leaf());
|
||||
pallet_mmr::verify_leaf_proof::<MmrHashing, _>(root, node, proof)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,18 +669,6 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_currency_exchange::RialtoCurrencyExchangeApi<Block, exchange::EthereumTransactionInclusionProof> for Runtime {
|
||||
fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool {
|
||||
BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof)
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_currency_exchange::KovanCurrencyExchangeApi<Block, exchange::EthereumTransactionInclusionProof> for Runtime {
|
||||
fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool {
|
||||
BridgeKovanCurrencyExchange::filter_transaction_proof(&proof)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
||||
fn validate_transaction(
|
||||
source: TransactionSource,
|
||||
@@ -700,13 +685,152 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> sp_consensus_aura::SlotDuration {
|
||||
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
|
||||
impl sp_consensus_babe::BabeApi<Block> for Runtime {
|
||||
fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
|
||||
// The choice of `c` parameter (where `1 - c` represents the
|
||||
// probability of a slot being empty), is done in accordance to the
|
||||
// slot duration and expected target block time, for safely
|
||||
// resisting network delays of maximum two seconds.
|
||||
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
|
||||
sp_consensus_babe::BabeGenesisConfiguration {
|
||||
slot_duration: Babe::slot_duration(),
|
||||
epoch_length: EpochDuration::get(),
|
||||
c: BABE_GENESIS_EPOCH_CONFIG.c,
|
||||
genesis_authorities: Babe::authorities().to_vec(),
|
||||
randomness: Babe::randomness(),
|
||||
allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots,
|
||||
}
|
||||
}
|
||||
|
||||
fn authorities() -> Vec<AuraId> {
|
||||
Aura::authorities()
|
||||
fn current_epoch_start() -> sp_consensus_babe::Slot {
|
||||
Babe::current_epoch_start()
|
||||
}
|
||||
|
||||
fn current_epoch() -> sp_consensus_babe::Epoch {
|
||||
Babe::current_epoch()
|
||||
}
|
||||
|
||||
fn next_epoch() -> sp_consensus_babe::Epoch {
|
||||
Babe::next_epoch()
|
||||
}
|
||||
|
||||
fn generate_key_ownership_proof(
|
||||
_slot: sp_consensus_babe::Slot,
|
||||
_authority_id: sp_consensus_babe::AuthorityId,
|
||||
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
|
||||
None
|
||||
}
|
||||
|
||||
fn submit_report_equivocation_unsigned_extrinsic(
|
||||
equivocation_proof: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
|
||||
key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
|
||||
) -> Option<()> {
|
||||
let key_owner_proof = key_owner_proof.decode()?;
|
||||
|
||||
Babe::submit_unsigned_equivocation_report(
|
||||
equivocation_proof,
|
||||
key_owner_proof,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl polkadot_primitives::v1::ParachainHost<Block, Hash, BlockNumber> for Runtime {
|
||||
fn validators() -> Vec<polkadot_primitives::v1::ValidatorId> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::validators::<Runtime>()
|
||||
}
|
||||
|
||||
fn validator_groups() -> (
|
||||
Vec<Vec<polkadot_primitives::v1::ValidatorIndex>>,
|
||||
polkadot_primitives::v1::GroupRotationInfo<BlockNumber>,
|
||||
) {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::<Runtime>()
|
||||
}
|
||||
|
||||
fn availability_cores() -> Vec<polkadot_primitives::v1::CoreState<Hash, BlockNumber>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::<Runtime>()
|
||||
}
|
||||
|
||||
fn persisted_validation_data(
|
||||
para_id: polkadot_primitives::v1::Id,
|
||||
assumption: polkadot_primitives::v1::OccupiedCoreAssumption,
|
||||
)
|
||||
-> Option<polkadot_primitives::v1::PersistedValidationData<Hash, BlockNumber>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::<Runtime>(para_id, assumption)
|
||||
}
|
||||
|
||||
fn assumed_validation_data(
|
||||
para_id: polkadot_primitives::v1::Id,
|
||||
expected_persisted_validation_data_hash: Hash,
|
||||
) -> Option<(polkadot_primitives::v1::PersistedValidationData<Hash, BlockNumber>, polkadot_primitives::v1::ValidationCodeHash)> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::<Runtime>(para_id, expected_persisted_validation_data_hash)
|
||||
}
|
||||
|
||||
fn check_validation_outputs(
|
||||
para_id: polkadot_primitives::v1::Id,
|
||||
outputs: polkadot_primitives::v1::CandidateCommitments,
|
||||
) -> bool {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::check_validation_outputs::<Runtime>(para_id, outputs)
|
||||
}
|
||||
|
||||
fn session_index_for_child() -> polkadot_primitives::v1::SessionIndex {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::<Runtime>()
|
||||
}
|
||||
|
||||
fn validation_code(
|
||||
para_id: polkadot_primitives::v1::Id,
|
||||
assumption: polkadot_primitives::v1::OccupiedCoreAssumption,
|
||||
)
|
||||
-> Option<polkadot_primitives::v1::ValidationCode> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::<Runtime>(para_id, assumption)
|
||||
}
|
||||
|
||||
fn candidate_pending_availability(
|
||||
para_id: polkadot_primitives::v1::Id,
|
||||
) -> Option<polkadot_primitives::v1::CommittedCandidateReceipt<Hash>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::<Runtime>(para_id)
|
||||
}
|
||||
|
||||
fn candidate_events() -> Vec<polkadot_primitives::v1::CandidateEvent<Hash>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::candidate_events::<Runtime, _>(|ev| {
|
||||
match ev {
|
||||
Event::Inclusion(ev) => {
|
||||
Some(ev)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option<polkadot_primitives::v1::SessionInfo> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::session_info::<Runtime>(index)
|
||||
}
|
||||
|
||||
fn dmq_contents(
|
||||
recipient: polkadot_primitives::v1::Id,
|
||||
) -> Vec<polkadot_primitives::v1::InboundDownwardMessage<BlockNumber>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::<Runtime>(recipient)
|
||||
}
|
||||
|
||||
fn inbound_hrmp_channels_contents(
|
||||
recipient: polkadot_primitives::v1::Id
|
||||
) -> BTreeMap<polkadot_primitives::v1::Id, Vec<polkadot_primitives::v1::InboundHrmpMessage<BlockNumber>>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::<Runtime>(recipient)
|
||||
}
|
||||
|
||||
fn validation_code_by_hash(
|
||||
hash: polkadot_primitives::v1::ValidationCodeHash,
|
||||
) -> Option<polkadot_primitives::v1::ValidationCode> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::<Runtime>(hash)
|
||||
}
|
||||
|
||||
fn on_chain_votes() -> Option<polkadot_primitives::v1::ScrapedOnChainVotes<Hash>> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::<Runtime>()
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityDiscoveryId> {
|
||||
polkadot_runtime_parachains::runtime_api_impl::v1::relevant_authority_ids::<Runtime>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,6 +859,10 @@ impl_runtime_apis! {
|
||||
}
|
||||
|
||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||
fn current_set_id() -> fg_primitives::SetId {
|
||||
Grandpa::current_set_id()
|
||||
}
|
||||
|
||||
fn grandpa_authorities() -> GrandpaAuthorityList {
|
||||
Grandpa::grandpa_authorities()
|
||||
}
|
||||
@@ -781,20 +909,11 @@ impl_runtime_apis! {
|
||||
begin: bp_messages::MessageNonce,
|
||||
end: bp_messages::MessageNonce,
|
||||
) -> Vec<bp_messages::MessageDetails<Balance>> {
|
||||
(begin..=end).filter_map(|nonce| {
|
||||
let message_data = BridgeMillauMessages::outbound_message_data(lane, nonce)?;
|
||||
let decoded_payload = millau_messages::ToMillauMessagePayload::decode(
|
||||
&mut &message_data.payload[..]
|
||||
).ok()?;
|
||||
Some(bp_messages::MessageDetails {
|
||||
nonce,
|
||||
dispatch_weight: decoded_payload.weight,
|
||||
size: message_data.payload.len() as _,
|
||||
delivery_and_dispatch_fee: message_data.fee,
|
||||
dispatch_fee_payment: decoded_payload.dispatch_fee_payment,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
bridge_runtime_common::messages_api::outbound_message_details::<
|
||||
Runtime,
|
||||
WithMillauMessagesInstance,
|
||||
WithMillauMessageBridge,
|
||||
>(lane, begin, end)
|
||||
}
|
||||
|
||||
fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce {
|
||||
@@ -829,18 +948,11 @@ impl_runtime_apis! {
|
||||
use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
|
||||
use frame_support::traits::StorageInfoTrait;
|
||||
|
||||
list_benchmark!(
|
||||
list,
|
||||
extra,
|
||||
pallet_bridge_currency_exchange,
|
||||
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
|
||||
);
|
||||
list_benchmark!(
|
||||
list,
|
||||
extra,
|
||||
pallet_bridge_messages,
|
||||
MessagesBench::<Runtime, WithMillauMessagesInstance>
|
||||
);
|
||||
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
|
||||
|
||||
let mut list = Vec::<BenchmarkList>::new();
|
||||
|
||||
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithMillauMessagesInstance>);
|
||||
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa);
|
||||
|
||||
let storage_info = AllPalletsWithSystem::storage_info();
|
||||
@@ -873,46 +985,6 @@ impl_runtime_apis! {
|
||||
let mut batches = Vec::<BenchmarkBatch>::new();
|
||||
let params = (&config, &whitelist);
|
||||
|
||||
use pallet_bridge_currency_exchange::benchmarking::{
|
||||
Pallet as BridgeCurrencyExchangeBench,
|
||||
Config as BridgeCurrencyExchangeConfig,
|
||||
ProofParams as BridgeCurrencyExchangeProofParams,
|
||||
};
|
||||
|
||||
impl BridgeCurrencyExchangeConfig<KovanCurrencyExchange> for Runtime {
|
||||
fn make_proof(
|
||||
proof_params: BridgeCurrencyExchangeProofParams<AccountId>,
|
||||
) -> crate::exchange::EthereumTransactionInclusionProof {
|
||||
use bp_currency_exchange::DepositInto;
|
||||
|
||||
if proof_params.recipient_exists {
|
||||
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
|
||||
proof_params.recipient.clone(),
|
||||
ExistentialDeposit::get(),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
let (transaction, receipt) = crate::exchange::prepare_ethereum_transaction(
|
||||
&proof_params.recipient,
|
||||
|tx| {
|
||||
// our runtime only supports transactions where data is exactly 32 bytes long
|
||||
// (receiver key)
|
||||
// => we are ignoring `transaction_size_factor` here
|
||||
tx.value = (ExistentialDeposit::get() * 10).into();
|
||||
},
|
||||
);
|
||||
let transactions = sp_std::iter::repeat((transaction, receipt))
|
||||
.take(1 + proof_params.proof_size_factor as usize)
|
||||
.collect::<Vec<_>>();
|
||||
let block_hash = crate::exchange::prepare_environment_for_claim::<Runtime, Kovan>(&transactions);
|
||||
crate::exchange::EthereumTransactionInclusionProof {
|
||||
block: block_hash,
|
||||
index: 0,
|
||||
proof: transactions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
||||
use bp_runtime::messages::DispatchFeePayment;
|
||||
use bridge_runtime_common::messages;
|
||||
@@ -981,7 +1053,7 @@ impl_runtime_apis! {
|
||||
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
|
||||
_ => vec![],
|
||||
};
|
||||
let call = Call::System(SystemCall::remark(remark));
|
||||
let call = Call::System(SystemCall::remark { remark });
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
|
||||
let millau_account_id: bp_millau::AccountId = Default::default();
|
||||
@@ -1001,14 +1073,12 @@ impl_runtime_apis! {
|
||||
Self::endow_account(&rialto_public.clone().into_account());
|
||||
}
|
||||
|
||||
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::<
|
||||
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
|
||||
>(
|
||||
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key(
|
||||
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
|
||||
&message_key.lane_id, message_key.nonce,
|
||||
).0;
|
||||
let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::<
|
||||
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
|
||||
>(
|
||||
let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key(
|
||||
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
|
||||
&lane_id,
|
||||
).0;
|
||||
|
||||
@@ -1054,9 +1124,8 @@ impl_runtime_apis! {
|
||||
|
||||
prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _>(
|
||||
params,
|
||||
|lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::<
|
||||
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
|
||||
>(
|
||||
|lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key(
|
||||
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
|
||||
&lane_id,
|
||||
).0,
|
||||
|state_root| bp_millau::Header::new(
|
||||
@@ -1082,12 +1151,6 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
add_benchmark!(
|
||||
params,
|
||||
batches,
|
||||
pallet_bridge_currency_exchange,
|
||||
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
|
||||
);
|
||||
add_benchmark!(
|
||||
params,
|
||||
batches,
|
||||
@@ -1104,8 +1167,8 @@ impl_runtime_apis! {
|
||||
/// Millau account ownership digest from Rialto.
|
||||
///
|
||||
/// The byte vector returned by this function should be signed with a Millau account private key.
|
||||
/// This way, the owner of `rialto_account_id` on Rialto proves that the Millau account private key
|
||||
/// is also under his control.
|
||||
/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private
|
||||
/// key is also under his control.
|
||||
pub fn rialto_to_millau_account_ownership_digest<Call, AccountId, SpecVersion>(
|
||||
millau_call: &Call,
|
||||
rialto_account_id: AccountId,
|
||||
@@ -1128,48 +1191,8 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bp_currency_exchange::DepositInto;
|
||||
use bridge_runtime_common::messages;
|
||||
|
||||
fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) {
|
||||
let mut ext: sp_io::TestExternalities =
|
||||
SystemConfig::default().build_storage::<Runtime>().unwrap().into();
|
||||
ext.execute_with(|| {
|
||||
// initially issuance is zero
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
|
||||
0,
|
||||
);
|
||||
|
||||
// create account
|
||||
let account: AccountId = [1u8; 32].into();
|
||||
let initial_amount = ExistentialDeposit::get();
|
||||
let deposited =
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||
&account,
|
||||
initial_amount,
|
||||
);
|
||||
drop(deposited);
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
|
||||
initial_amount,
|
||||
);
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&account),
|
||||
initial_amount,
|
||||
);
|
||||
|
||||
// run test
|
||||
let total_issuance_change = test(account);
|
||||
|
||||
// check that total issuance has changed by `run_deposit_into_test`
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
|
||||
initial_amount + total_issuance_change,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_rialto_message_lane_weights_are_correct() {
|
||||
type Weights = pallet_bridge_messages::weights::RialtoWeight<Runtime>;
|
||||
@@ -1179,6 +1202,7 @@ mod tests {
|
||||
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
|
||||
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
|
||||
DbWeight::get(),
|
||||
);
|
||||
|
||||
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
|
||||
@@ -1206,50 +1230,16 @@ mod tests {
|
||||
max_incoming_inbound_lane_data_proof_size,
|
||||
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
|
||||
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
|
||||
DbWeight::get(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deposit_into_existing_account_works() {
|
||||
run_deposit_into_test(|existing_account| {
|
||||
let initial_amount =
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
|
||||
&existing_account,
|
||||
);
|
||||
let additional_amount = 10_000;
|
||||
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
|
||||
existing_account.clone(),
|
||||
additional_amount,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
|
||||
&existing_account
|
||||
),
|
||||
initial_amount + additional_amount,
|
||||
);
|
||||
additional_amount
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deposit_into_new_account_works() {
|
||||
run_deposit_into_test(|_| {
|
||||
let initial_amount = 0;
|
||||
let additional_amount = ExistentialDeposit::get() + 10_000;
|
||||
let new_account: AccountId = [42u8; 32].into();
|
||||
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
|
||||
new_account.clone(),
|
||||
additional_amount,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
|
||||
&new_account
|
||||
),
|
||||
initial_amount + additional_amount,
|
||||
);
|
||||
additional_amount
|
||||
});
|
||||
fn call_size() {
|
||||
const DOT_MAX_CALL_SZ: usize = 230;
|
||||
assert!(core::mem::size_of::<pallet_bridge_grandpa::Call<Runtime>>() <= DOT_MAX_CALL_SZ);
|
||||
// FIXME: get this down to 230. https://github.com/paritytech/grandpa-bridge-gadget/issues/359
|
||||
const BEEFY_MAX_CALL_SZ: usize = 232;
|
||||
assert!(core::mem::size_of::<pallet_bridge_messages::Call<Runtime>>() <= BEEFY_MAX_CALL_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,25 +31,34 @@ use frame_support::{
|
||||
weights::{DispatchClass, Weight},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
|
||||
use sp_std::{convert::TryFrom, ops::RangeInclusive};
|
||||
|
||||
/// Initial value of `MillauToRialtoConversionRate` parameter.
|
||||
pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV);
|
||||
pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 =
|
||||
FixedU128::from_inner(FixedU128::DIV);
|
||||
/// Initial value of `MillauFeeMultiplier` parameter.
|
||||
pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV);
|
||||
|
||||
parameter_types! {
|
||||
/// Millau to Rialto conversion rate. Initially we treat both tokens as equal.
|
||||
pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE;
|
||||
/// Fee multiplier value at Millau chain.
|
||||
pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
/// Message payload for Rialto -> Millau messages.
|
||||
pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
|
||||
pub type ToMillauMessagePayload =
|
||||
messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
|
||||
|
||||
/// Message verifier for Rialto -> Millau messages.
|
||||
pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
|
||||
pub type ToMillauMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
|
||||
|
||||
/// Message payload for Millau -> Rialto messages.
|
||||
pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
|
||||
pub type FromMillauMessagePayload =
|
||||
messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
|
||||
|
||||
/// Encoded Rialto Call as it comes from Millau.
|
||||
pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>;
|
||||
@@ -59,14 +68,15 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi
|
||||
WithMillauMessageBridge,
|
||||
crate::Runtime,
|
||||
pallet_balances::Pallet<Runtime>,
|
||||
pallet_bridge_dispatch::DefaultInstance,
|
||||
(),
|
||||
>;
|
||||
|
||||
/// Messages proof for Millau -> Rialto messages.
|
||||
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
|
||||
|
||||
/// Messages delivery proof for Rialto -> Millau messages.
|
||||
pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof<bp_millau::Hash>;
|
||||
pub type ToMillauMessagesDeliveryProof =
|
||||
messages::source::FromBridgedChainMessagesDeliveryProof<bp_millau::Hash>;
|
||||
|
||||
/// Millau <-> Rialto message bridge.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
@@ -76,14 +86,16 @@ impl MessageBridge for WithMillauMessageBridge {
|
||||
const RELAYER_FEE_PERCENT: u32 = 10;
|
||||
const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID;
|
||||
const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
|
||||
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME;
|
||||
|
||||
type ThisChain = Rialto;
|
||||
type BridgedChain = Millau;
|
||||
type BridgedMessagesInstance = crate::WithMillauMessagesInstance;
|
||||
|
||||
fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance {
|
||||
bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance))
|
||||
.unwrap_or(bp_rialto::Balance::MAX)
|
||||
bp_rialto::Balance::try_from(
|
||||
MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance),
|
||||
)
|
||||
.unwrap_or(bp_rialto::Balance::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,11 +140,15 @@ impl messages::ThisChainWithMessages for Rialto {
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance {
|
||||
// `transaction` may represent transaction from the future, when multiplier value will
|
||||
// be larger, so let's use slightly increased value
|
||||
let multiplier = FixedU128::saturating_from_rational(110, 100)
|
||||
.saturating_mul(pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier());
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
|
||||
1,
|
||||
FixedU128::zero(),
|
||||
multiplier,
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
@@ -159,12 +175,15 @@ impl messages::BridgedChainWithMessages for Millau {
|
||||
|
||||
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
|
||||
// we don't want to relay too large messages + keep reserve for future upgrades
|
||||
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight());
|
||||
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(
|
||||
bp_millau::max_extrinsic_weight(),
|
||||
);
|
||||
|
||||
// we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` function
|
||||
// we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment`
|
||||
// function
|
||||
//
|
||||
// this bridge may be used to deliver all kind of messages, so we're not making any assumptions about
|
||||
// minimal dispatch weight here
|
||||
// this bridge may be used to deliver all kind of messages, so we're not making any
|
||||
// assumptions about minimal dispatch weight here
|
||||
|
||||
0..=upper_limit
|
||||
}
|
||||
@@ -195,11 +214,14 @@ impl messages::BridgedChainWithMessages for Millau {
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
|
||||
// we don't have a direct access to the value of multiplier at Millau chain
|
||||
// => it is a messages module parameter
|
||||
let multiplier = MillauFeeMultiplier::get();
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
|
||||
1,
|
||||
FixedU128::zero(),
|
||||
multiplier,
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
@@ -221,9 +243,11 @@ impl TargetHeaderChain<ToMillauMessagePayload, bp_millau::AccountId> for Millau
|
||||
fn verify_messages_delivery_proof(
|
||||
proof: Self::MessagesDeliveryProof,
|
||||
) -> Result<(LaneId, InboundLaneData<bp_rialto::AccountId>), Self::Error> {
|
||||
messages::source::verify_messages_delivery_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>(
|
||||
proof,
|
||||
)
|
||||
messages::source::verify_messages_delivery_proof::<
|
||||
WithMillauMessageBridge,
|
||||
Runtime,
|
||||
crate::MillauGrandpaInstance,
|
||||
>(proof)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,15 +264,16 @@ impl SourceHeaderChain<bp_millau::Balance> for Millau {
|
||||
proof: Self::MessagesProof,
|
||||
messages_count: u32,
|
||||
) -> Result<ProvedMessages<Message<bp_millau::Balance>>, Self::Error> {
|
||||
messages::target::verify_messages_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>(
|
||||
proof,
|
||||
messages_count,
|
||||
)
|
||||
messages::target::verify_messages_proof::<
|
||||
WithMillauMessageBridge,
|
||||
Runtime,
|
||||
crate::MillauGrandpaInstance,
|
||||
>(proof, messages_count)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rialto -> Millau message lane pallet parameters.
|
||||
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)]
|
||||
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
|
||||
pub enum RialtoToMillauMessagesParameter {
|
||||
/// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`.
|
||||
MillauToRialtoConversionRate(FixedU128),
|
||||
@@ -257,9 +282,8 @@ pub enum RialtoToMillauMessagesParameter {
|
||||
impl MessagesParameter for RialtoToMillauMessagesParameter {
|
||||
fn save(&self) {
|
||||
match *self {
|
||||
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => {
|
||||
MillauToRialtoConversionRate::set(conversion_rate)
|
||||
}
|
||||
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) =>
|
||||
MillauToRialtoConversionRate::set(conversion_rate),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,7 +298,9 @@ mod tests {
|
||||
MessageKey,
|
||||
};
|
||||
use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount};
|
||||
use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload};
|
||||
use bridge_runtime_common::messages::target::{
|
||||
FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload,
|
||||
};
|
||||
use frame_support::{
|
||||
traits::Currency,
|
||||
weights::{GetDispatchInfo, WeightToFeePolynomial},
|
||||
@@ -286,12 +312,15 @@ mod tests {
|
||||
// this test actually belongs to the `bridge-runtime-common` crate, but there we have no
|
||||
// mock runtime. Making another one there just for this test, given that both crates
|
||||
// live n single repo is an overkill
|
||||
let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::<Runtime>().unwrap().into();
|
||||
let mut ext: sp_io::TestExternalities =
|
||||
SystemConfig::default().build_storage::<Runtime>().unwrap().into();
|
||||
ext.execute_with(|| {
|
||||
let bridge = MILLAU_CHAIN_ID;
|
||||
let call: Call = SystemCall::remark(vec![]).into();
|
||||
let call: Call = SystemCall::remark { remark: vec![] }.into();
|
||||
let dispatch_weight = call.get_dispatch_info().weight;
|
||||
let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(&dispatch_weight);
|
||||
let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(
|
||||
&dispatch_weight,
|
||||
);
|
||||
assert!(dispatch_fee > 0);
|
||||
|
||||
// create relayer account with minimal balance
|
||||
@@ -303,12 +332,13 @@ mod tests {
|
||||
);
|
||||
|
||||
// create dispatch account with minimal balance + dispatch fee
|
||||
let dispatch_account = derive_account_id::<<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId>(
|
||||
bridge,
|
||||
SourceAccount::Root,
|
||||
);
|
||||
let dispatch_account = derive_account_id::<
|
||||
<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId,
|
||||
>(bridge, SourceAccount::Root);
|
||||
let dispatch_account =
|
||||
<Runtime as pallet_bridge_dispatch::Config>::AccountIdConverter::convert(dispatch_account);
|
||||
<Runtime as pallet_bridge_dispatch::Config>::AccountIdConverter::convert(
|
||||
dispatch_account,
|
||||
);
|
||||
let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||
&dispatch_account,
|
||||
initial_amount + dispatch_fee,
|
||||
@@ -318,10 +348,7 @@ mod tests {
|
||||
FromMillauMessageDispatch::dispatch(
|
||||
&relayer_account,
|
||||
DispatchMessage {
|
||||
key: MessageKey {
|
||||
lane_id: Default::default(),
|
||||
nonce: 0,
|
||||
},
|
||||
key: MessageKey { lane_id: Default::default(), nonce: 0 },
|
||||
data: DispatchMessageData {
|
||||
payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> {
|
||||
spec_version: VERSION.spec_version,
|
||||
@@ -337,11 +364,15 @@ mod tests {
|
||||
|
||||
// ensure that fee has been transferred from dispatch to relayer account
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&relayer_account),
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
|
||||
&relayer_account
|
||||
),
|
||||
initial_amount + dispatch_fee,
|
||||
);
|
||||
assert_eq!(
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&dispatch_account),
|
||||
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
|
||||
&dispatch_account
|
||||
),
|
||||
initial_amount,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Parachains support in Rialto runtime.
|
||||
|
||||
use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots};
|
||||
|
||||
use frame_support::{parameter_types, weights::Weight};
|
||||
use frame_system::EnsureRoot;
|
||||
use polkadot_primitives::v1::ValidatorIndex;
|
||||
use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots};
|
||||
use polkadot_runtime_parachains::{
|
||||
configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp,
|
||||
inclusion as parachains_inclusion, initializer as parachains_initializer,
|
||||
origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler,
|
||||
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
|
||||
};
|
||||
|
||||
/// Special `RewardValidators` that does nothing ;)
|
||||
pub struct RewardValidators;
|
||||
impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidators {
|
||||
fn reward_backing(_: impl IntoIterator<Item = ValidatorIndex>) {}
|
||||
fn reward_bitfields(_: impl IntoIterator<Item = ValidatorIndex>) {}
|
||||
}
|
||||
|
||||
// all required parachain modules from `polkadot-runtime-parachains` crate
|
||||
|
||||
impl parachains_configuration::Config for Runtime {
|
||||
type WeightInfo = parachains_configuration::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl parachains_dmp::Config for Runtime {}
|
||||
|
||||
impl parachains_hrmp::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Origin = Origin;
|
||||
type Currency = Balances;
|
||||
}
|
||||
|
||||
impl parachains_inclusion::Config for Runtime {
|
||||
type Event = Event;
|
||||
type RewardValidators = RewardValidators;
|
||||
type DisputesHandler = ();
|
||||
}
|
||||
|
||||
impl parachains_initializer::Config for Runtime {
|
||||
type Randomness = pallet_babe::RandomnessFromOneEpochAgo<Runtime>;
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl parachains_origin::Config for Runtime {}
|
||||
|
||||
impl parachains_paras::Config for Runtime {
|
||||
type Origin = Origin;
|
||||
type Event = Event;
|
||||
type WeightInfo = parachains_paras::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl parachains_paras_inherent::Config for Runtime {
|
||||
type WeightInfo = parachains_paras_inherent::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl parachains_scheduler::Config for Runtime {}
|
||||
|
||||
impl parachains_session_info::Config for Runtime {}
|
||||
|
||||
impl parachains_shared::Config for Runtime {}
|
||||
|
||||
parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
type Event = Event;
|
||||
type UmpSink = ();
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
// required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing
|
||||
|
||||
parameter_types! {
|
||||
pub const ParaDeposit: Balance = 0;
|
||||
pub const DataDepositPerByte: Balance = 0;
|
||||
}
|
||||
|
||||
impl paras_registrar::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Origin = Origin;
|
||||
type Currency = Balances;
|
||||
type OnSwap = Slots;
|
||||
type ParaDeposit = ParaDeposit;
|
||||
type DataDepositPerByte = DataDepositPerByte;
|
||||
type WeightInfo = paras_registrar::TestWeightInfo;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const LeasePeriod: BlockNumber = 10 * bp_rialto::MINUTES;
|
||||
}
|
||||
|
||||
impl slots::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Currency = Balances;
|
||||
type Registrar = Registrar;
|
||||
type LeasePeriod = LeasePeriod;
|
||||
type WeightInfo = slots::TestWeightInfo;
|
||||
type LeaseOffset = ();
|
||||
}
|
||||
|
||||
impl paras_sudo_wrapper::Config for Runtime {}
|
||||
|
||||
pub struct ZeroWeights;
|
||||
|
||||
impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights {
|
||||
fn reserve() -> Weight {
|
||||
0
|
||||
}
|
||||
fn register() -> Weight {
|
||||
0
|
||||
}
|
||||
fn force_register() -> Weight {
|
||||
0
|
||||
}
|
||||
fn deregister() -> Weight {
|
||||
0
|
||||
}
|
||||
fn swap() -> Weight {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights {
|
||||
fn force_lease() -> Weight {
|
||||
0
|
||||
}
|
||||
fn manage_lease_period_start(_c: u32, _t: u32) -> Weight {
|
||||
0
|
||||
}
|
||||
fn clear_all_leases() -> Weight {
|
||||
0
|
||||
}
|
||||
fn trigger_onboard() -> Weight {
|
||||
0
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
// Copyright 2020-2021 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/>.
|
||||
|
||||
//! Configuration parameters for the Rialto PoA chain.
|
||||
|
||||
use crate::exchange::EthereumTransactionInclusionProof;
|
||||
|
||||
use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256};
|
||||
use bp_header_chain::InclusionProofVerifier;
|
||||
use frame_support::RuntimeDebug;
|
||||
use hex_literal::hex;
|
||||
use pallet_bridge_eth_poa::{
|
||||
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration,
|
||||
ValidatorsSource,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub const FinalityVotesCachingInterval: Option<u64> = Some(8);
|
||||
pub BridgeAuraConfiguration: AuraConfiguration =
|
||||
aura_configuration();
|
||||
pub BridgeValidatorsConfiguration: ValidatorsConfiguration =
|
||||
validators_configuration();
|
||||
}
|
||||
|
||||
/// Max number of finalized headers to keep.
|
||||
const FINALIZED_HEADERS_TO_KEEP: u64 = 5_000;
|
||||
|
||||
/// Aura engine configuration for Rialto chain.
|
||||
pub fn aura_configuration() -> AuraConfiguration {
|
||||
AuraConfiguration {
|
||||
empty_steps_transition: 0xfffffffff,
|
||||
strict_empty_steps_transition: 0,
|
||||
validate_step_transition: 0,
|
||||
validate_score_transition: 0,
|
||||
two_thirds_majority_transition: u64::MAX,
|
||||
min_gas_limit: 0x1388.into(),
|
||||
max_gas_limit: U256::MAX,
|
||||
maximum_extra_data_size: 0x20,
|
||||
}
|
||||
}
|
||||
|
||||
/// Validators configuration for Rialto PoA chain.
|
||||
pub fn validators_configuration() -> ValidatorsConfiguration {
|
||||
ValidatorsConfiguration::Single(ValidatorsSource::List(genesis_validators()))
|
||||
}
|
||||
|
||||
/// Genesis validators set of Rialto PoA chain.
|
||||
pub fn genesis_validators() -> Vec<Address> {
|
||||
vec![
|
||||
hex!("005e714f896a8b7cede9d38688c1a81de72a58e4").into(),
|
||||
hex!("007594304039c2937a12220338aab821d819f5a4").into(),
|
||||
hex!("004e7a39907f090e19b0b80a277e77b72b22e269").into(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Genesis header of the Rialto PoA chain.
|
||||
///
|
||||
/// To obtain genesis header from a running node, invoke:
|
||||
/// ```bash
|
||||
/// $ http localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["earliest", false]' -v
|
||||
/// ```
|
||||
pub fn genesis_header() -> AuraHeader {
|
||||
AuraHeader {
|
||||
parent_hash: Default::default(),
|
||||
timestamp: 0,
|
||||
number: 0,
|
||||
author: Default::default(),
|
||||
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
|
||||
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
|
||||
extra_data: vec![],
|
||||
state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(),
|
||||
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
|
||||
log_bloom: Default::default(),
|
||||
gas_used: Default::default(),
|
||||
gas_limit: 0x222222.into(),
|
||||
difficulty: 0x20000.into(),
|
||||
seal: vec![vec![0x80], {
|
||||
let mut vec = vec![0xb8, 0x41];
|
||||
vec.resize(67, 0);
|
||||
vec
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
/// Rialto PoA headers pruning strategy.
|
||||
///
|
||||
/// We do not prune unfinalized headers because exchange module only accepts
|
||||
/// claims from finalized headers. And if we're pruning unfinalized headers, then
|
||||
/// some claims may never be accepted.
|
||||
#[derive(Default, RuntimeDebug)]
|
||||
pub struct PruningStrategy;
|
||||
|
||||
impl TPruningStrategy for PruningStrategy {
|
||||
fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 {
|
||||
best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP)
|
||||
}
|
||||
}
|
||||
|
||||
/// `ChainTime` provider
|
||||
#[derive(Default)]
|
||||
pub struct ChainTime;
|
||||
|
||||
impl TChainTime for ChainTime {
|
||||
fn is_timestamp_ahead(&self, timestamp: u64) -> bool {
|
||||
let now = super::Timestamp::now();
|
||||
timestamp > now
|
||||
}
|
||||
}
|
||||
|
||||
/// The Rialto PoA Blockchain as seen by the runtime.
|
||||
pub struct RialtoBlockchain;
|
||||
|
||||
impl InclusionProofVerifier for RialtoBlockchain {
|
||||
type Transaction = RawTransaction;
|
||||
type TransactionInclusionProof = EthereumTransactionInclusionProof;
|
||||
|
||||
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> {
|
||||
let is_transaction_finalized =
|
||||
crate::BridgeRialtoPoa::verify_transaction_finalized(proof.block, proof.index, &proof.proof);
|
||||
|
||||
if !is_transaction_finalized {
|
||||
return None;
|
||||
}
|
||||
|
||||
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn genesis_hash_matches() {
|
||||
assert_eq!(
|
||||
genesis_header().compute_hash(),
|
||||
hex!("1468e1a0fa20d30025a5a0f87e1cced4fdc393b84b7d2850b11ca5863db482cb").into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pruning_strategy_keeps_enough_headers() {
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 1_000),
|
||||
0,
|
||||
"1_000 <= 5_000 => nothing should be pruned yet",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 5_000),
|
||||
0,
|
||||
"5_000 <= 5_000 => nothing should be pruned yet",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PruningStrategy::default().pruning_upper_bound(100_000, 10_000),
|
||||
5_000,
|
||||
"5_000 <= 10_000 => we're ready to prune first 5_000 headers",
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user