mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 19:51:02 +00:00
Squashed 'bridges/' changes from 23dda62482..407bf44a8a
407bf44a8a add missing license header (#1204) 9babb19810 Custom relay strategy (#1198) c287872a11 fix clippy things (#1200) 3a40e62789 Expose some const value and type (#1186) 32b61476d1 increase sleep before connectingMillau (#1195) aabe7041fa revert messages transactions mortality (#1194) 3651f4f909 Message transactions mortality (#1191) 364d6e155d Bump dependencies (#1180) f0389acc08 cargo +nightly fmt --all (#1192) b270b6a016 Unify error enums in substrate and ethereum clients with `thiserror` (#1094) 58c4946f74 Limit max call size of Rialto/Millau runtimes (#1187) fd56a8cd56 Add UI to the deployment (#1047) 16f01dc736 Westend -> Millau alerts are pending before notifications are sent (#1184) 5628c11ece replace collective flip with babe randomness in Rialto (#1188) 1094a63b00 ignore another (pretty bad) RUSTSEC (#1185) 379fe323ea fix/ignore cargo deny issues (#1183) 92af5e6e64 additional log in finality relay + rephrase "failed" (#1182) b996a3b681 Rialto parachain in test deployments (#1178) 28d9332b44 Resubmit transactions strategy for Polkadot/Kusama (#1175) d0172c6847 Playing with CI (#1179) fb6f42456d fix checks order when registering parachain (#1177) ee828c005a Register-parachain subcommand of substrate-relay (#1170) 8cd2b1a112 Token swap pallet benchmarks (#1174) bb811accb1 fix collision with westend bridge (#1172) 8d2fba70ed add token swaps to test deployments (#1169) b6d1bdfe2c publish rialto parachain collator image (#1171) 834ae4a10a Fix OutboundLaneData types (#1159) 5ee0ea1626 copypasted -> copied (#1168) c3bb835f18 fix spelling (#1167) f90d041dc9 Upgrade `jsonrpsee` to v0.3 (#1051) 598c9b6d0d add some basic tests for swap tokens (#1164) 05e88c61f5 publish images when tag of specific format(e.g. v2021-09-27 + v2021-09-27-1) is published (#1166) 7f3f94a6e0 Fix CI again (#1165) ff37de332f Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153) 36fbba839b fix clippy warning (#1163) 16da44d018 explicit wasm build (#1158) c9c8226449 Match substrate's fmt (#1148) 2fdd7f3e5e Fix/ignore clippy warnings (#1157) 43dfcc2686 Adding LookupAddress (#1156) 951eaa5582 Add rialto-parachain runtime and node (#1142) 803d266d61 Rename MessageId -> BridgeMessageId (#1152) 5f234484fc Box large arguments of GRANDPA pallet (#1154) cf9abc1011 Fix spelling (#1150) ab83ba2e58 Relay subcommand that performs token RLT <> MLAU token swap (#1141) 832536caf0 Polkadot <> Kusama relayers (#1122) 6d0daa8975 Add `OnMessageAccepted` callback (#1134) 5d03a20b3e Integrate token swap pallet into Millau runtime (#1099) ea4cfa833e Adding MultiAddress type and ValidationCodeHash (#1139) c20325a784 Add tests for `Raw` and `BridgeSendMessage` enum `Call` variants (#1125) 6d802416e2 increase pause before pining Rialto nodes (#1137) b54fa56b62 calculate fee using full message payload (#1132) ca5d8178f5 Add parachain pallets to rialto runtime (#1053) 9eaae4142e fix transaction resubmitter limits for Millau -> Rialto transactions (#1135) 9d4e17783c add --mandatory-headers-only cli option to complex relay (#1129) 1c5e0ec1cb Add local CI info to README (#1131) a8e0929e14 chore: spellchecker fixes (#1130) 3b8e2118e3 set fee for importing mandatory headers to zero (#1127) 49bba9aa52 another bunch of words for spellchecker (#1128) 8a72eafef6 Increase pause before messages generation start (#1126) 1f0ba9a191 Move some associated types from relay_substrate_client::Chain to bp_runtime::Chain (#1087) 74bc1a5b54 Transactions resubmitter (#1083) 21ba001f26 log max balance drop when sending message (#1117) 638a7ddffa Code Cleaning (#1124) be6555c51b Fix buildah logout (#1120) 87539c4a98 Format code work (#1116) 526fe7fdd7 fix spelling (#1119) bd4ce7f241 Fix spelling (#1118) 3c1147858e added missing constants to Kusama/Polkadot primitives (#1114) 52093b22ab Fix delivery transaction estimation used by rational relayer (#1109) 77a2f2fbed Remove fund account checks from upgrade. (#1111) 824334802b Rename param and update comment (#1108) d7784bfe06 Fix spellcheck (#1110) 0b18f5906a Refactor substrate messages source and substrate messages target (#1105) b27240bbff fix compilation (#1107) 9697da4fe8 Emit mortal transactions from relay (#1073) b29396c077 Change vault vars type to env vars (#1084) 35e0bbdc0c Make clippy mandatory. (#1103) a517e8541f Remove unused deps (#1102) 873dae608a Remove unnessary deps (#1101) 13450b74ee Stored conversion rate updater (#1005) 74389829f3 [BREAKING] Migrate messages pallet to frame v2 (#1088) 424da938dd README fix (#1100) 865744c909 upgrade currency exchange pallet to frame v2 (#1097) b5038148b3 Add missing docs (#1095) 0791e911c1 Common crate for substrate-relay (#1082) 3834c9d880 Update high-level-overview.md (#1093) c93553face Increase the time window for messaging alerts. (#1092) 8b9cc3cecd migrate pallet-shift-session-manager to frame v2 (#1090) dc91813c22 migrate eth PoA pallet to frame v2 (#1091) f16bb098cc Migrate dispatch pallet to frame v2 (#1089) 19f4325348 Bridge/This Chain Ids should be exposed as constants on pallet level. (#1085) 6381122df7 Change ChainSpec::from_genesis for Rialto and Millau chains to reflect the chain names. (#1079) 0f1d33e973 Make CI happy again (#1086) 238e65d96f fix typo (#1080) fc008457b6 Token-swap-over-bridge pallet (#944) 3fb97fa5ef Fix full spellcheck (#1076) eae4ed7170 fixed wrong trace (#1075) 219a0fad04 merge two weight-related loops in messages pallet (#1071) fc85632fdb increase_message_fee depends on stored mesage size (#1066) 530f37a23b companion for https://github.com/paritytech/polkadot/pull/3507 (#1067) 53b8cba683 sc_basic_authorship=trace for millau nodes (#1074) 9874e05e98 Improve traces of message generator scripts (#1069) 7b5ee84fbb extract message_details impl into runtime common (#1070) 5a4aed5a8b refund weight for mot pruning messages (#1062) 90e3d1e111 Fix Westend -> Millau sync (#1064) 427d30ddfc When restarting client, also "restart" tokio runtime (#1065) d47c05eeef Change get pipeline sensitive variables from Vault instead of GitLab settings (#1063) d775a85415 use tokio reactor to execute jsonrpsee futures (#1061) 15c8cd61cb Use BABE to author blocks on Rialto (previously: Aura) (#1050) 5186293500 Allow reading suri && password override from file (#1059) b506298262 Update jsonrpsee reference (#1049) 1734d00517 enable weight fee adjustent in Rialto/Millau (#1044) 607265afae Pay dispatch fee at target chain cli option (#1043) ce79ef91be bump dependencies before start referencing polkadot repo (#1048) 924fa24f6d Cli option for greedy relayer + run no-losses relayer by default (#1042) e21eba7b59 Yrong README Fixup + M1 Fixes (#1045) 20d08204a2 Confirm delivery detects when more than expected messages are confirmed (#1039) 994b846b52 pre and post dispatch weights of OnDeliveryConfirmed callback (#1040) 1dd5297e84 give real value to Rialto and Millau tokens (#1038) 035bee8715 Use real conversion rate in greedy relayer strategy (#1035) 9cfaecd0f7 fixed metrics prefix (#1037) 1d8d224937 Use kebab-case for bridge arguments (#1036) f30a4c79a6 Shared reference to conversion rate metric value (#1034) c34d7a5cbb estimate transaction fee (#1015) 93404b18bb change alert period from 2m to 10m for Westend -> Millau (GRANDPA or public node itself is lagging sometimes) (#1032) git-subtree-dir: bridges git-subtree-split: 407bf44a8a5f4e60aceef2dc755cd9ff09929ac3
This commit is contained in:
@@ -1,132 +0,0 @@
|
||||
[package]
|
||||
name = "rialto-runtime"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
homepage = "https://substrate.dev"
|
||||
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"] }
|
||||
hex-literal = "0.3"
|
||||
libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
serde = { version = "1.0.124", 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 }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
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 }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
libsecp256k1 = { version = "0.3.4", features = ["hmac"] }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-currency-exchange/std",
|
||||
"bp-eth-poa/std",
|
||||
"bp-header-chain/std",
|
||||
"bp-message-dispatch/std",
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-rialto/std",
|
||||
"bp-runtime/std",
|
||||
"bridge-runtime-common/std",
|
||||
"codec/std",
|
||||
"frame-benchmarking/std",
|
||||
"frame-executive/std",
|
||||
"frame-support/std",
|
||||
"frame-system-rpc-runtime-api/std",
|
||||
"frame-system/std",
|
||||
"log/std",
|
||||
"pallet-aura/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-bridge-currency-exchange/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-shift-session-manager/std",
|
||||
"pallet-sudo/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-transaction-payment-rpc-runtime-api/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"serde",
|
||||
"sp-api/std",
|
||||
"sp-block-builder/std",
|
||||
"sp-consensus-aura/std",
|
||||
"sp-core/std",
|
||||
"sp-finality-grandpa/std",
|
||||
"sp-inherents/std",
|
||||
"sp-io/std",
|
||||
"sp-offchain/std",
|
||||
"sp-runtime/std",
|
||||
"sp-session/std",
|
||||
"sp-std/std",
|
||||
"sp-transaction-pool/std",
|
||||
"sp-trie/std",
|
||||
"sp-version/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"bridge-runtime-common/runtime-benchmarks",
|
||||
"frame-benchmarking",
|
||||
"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,25 +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 substrate_wasm_builder::WasmBuilder;
|
||||
|
||||
fn main() {
|
||||
WasmBuilder::new()
|
||||
.with_current_project()
|
||||
.import_memory()
|
||||
.export_heap_base()
|
||||
.build()
|
||||
}
|
||||
@@ -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 tx 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_value()) + 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 ~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_value(),
|
||||
strict_empty_steps_transition: 0,
|
||||
validate_step_transition: 0x16e360,
|
||||
validate_score_transition: 0x41a3c4,
|
||||
two_thirds_majority_transition: u64::max_value(),
|
||||
min_gas_limit: 0x1388.into(),
|
||||
max_gas_limit: U256::max_value(),
|
||||
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",
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,349 +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/>.
|
||||
|
||||
//! Everything required to serve Millau <-> Rialto messages.
|
||||
|
||||
use crate::Runtime;
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::TargetHeaderChain,
|
||||
target_chain::{ProvedMessages, SourceHeaderChain},
|
||||
InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter,
|
||||
};
|
||||
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
|
||||
use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
weights::{DispatchClass, Weight},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use sp_runtime::{traits::Zero, 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);
|
||||
|
||||
parameter_types! {
|
||||
/// Millau to Rialto conversion rate. Initially we treat both tokens as equal.
|
||||
pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE;
|
||||
}
|
||||
|
||||
/// Message payload for Rialto -> Millau messages.
|
||||
pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
|
||||
|
||||
/// Message verifier for Rialto -> Millau messages.
|
||||
pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
|
||||
|
||||
/// Message payload for Millau -> Rialto messages.
|
||||
pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
|
||||
|
||||
/// Encoded Rialto Call as it comes from Millau.
|
||||
pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>;
|
||||
|
||||
/// Call-dispatch based message dispatch for Millau -> Rialto messages.
|
||||
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
||||
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>;
|
||||
|
||||
/// Millau <-> Rialto message bridge.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct WithMillauMessageBridge;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rialto chain from message lane point of view.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct Rialto;
|
||||
|
||||
impl messages::ChainWithMessages for Rialto {
|
||||
type Hash = bp_rialto::Hash;
|
||||
type AccountId = bp_rialto::AccountId;
|
||||
type Signer = bp_rialto::AccountSigner;
|
||||
type Signature = bp_rialto::Signature;
|
||||
type Weight = Weight;
|
||||
type Balance = bp_rialto::Balance;
|
||||
}
|
||||
|
||||
impl messages::ThisChainWithMessages for Rialto {
|
||||
type Call = crate::Call;
|
||||
|
||||
fn is_outbound_lane_enabled(lane: &LaneId) -> bool {
|
||||
*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]
|
||||
}
|
||||
|
||||
fn maximal_pending_messages_at_outbound_lane() -> MessageNonce {
|
||||
MessageNonce::MAX
|
||||
}
|
||||
|
||||
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
||||
let inbound_data_size = InboundLaneData::<bp_rialto::AccountId>::encoded_size_hint(
|
||||
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
.unwrap_or(u32::MAX);
|
||||
|
||||
MessageTransaction {
|
||||
dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||
size: inbound_data_size
|
||||
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_rialto::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance {
|
||||
// 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(),
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Millau chain from message lane point of view.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct Millau;
|
||||
|
||||
impl messages::ChainWithMessages for Millau {
|
||||
type Hash = bp_millau::Hash;
|
||||
type AccountId = bp_millau::AccountId;
|
||||
type Signer = bp_millau::AccountSigner;
|
||||
type Signature = bp_millau::Signature;
|
||||
type Weight = Weight;
|
||||
type Balance = bp_millau::Balance;
|
||||
}
|
||||
|
||||
impl messages::BridgedChainWithMessages for Millau {
|
||||
fn maximal_extrinsic_size() -> u32 {
|
||||
bp_millau::max_extrinsic_size()
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// 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
|
||||
|
||||
0..=upper_limit
|
||||
}
|
||||
|
||||
fn estimate_delivery_transaction(
|
||||
message_payload: &[u8],
|
||||
include_pay_dispatch_fee_cost: bool,
|
||||
message_dispatch_weight: Weight,
|
||||
) -> MessageTransaction<Weight> {
|
||||
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
|
||||
let extra_bytes_in_payload = Weight::from(message_payload_len)
|
||||
.saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into());
|
||||
|
||||
MessageTransaction {
|
||||
dispatch_weight: extra_bytes_in_payload
|
||||
.saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
||||
.saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
||||
.saturating_sub(if include_pay_dispatch_fee_cost {
|
||||
0
|
||||
} else {
|
||||
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT
|
||||
})
|
||||
.saturating_add(message_dispatch_weight),
|
||||
size: message_payload_len
|
||||
.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_millau::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
|
||||
// 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(),
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetHeaderChain<ToMillauMessagePayload, bp_millau::AccountId> for Millau {
|
||||
type Error = &'static str;
|
||||
// The proof is:
|
||||
// - hash of the header this proof has been created with;
|
||||
// - the storage proof of one or several keys;
|
||||
// - id of the lane we prove state of.
|
||||
type MessagesDeliveryProof = ToMillauMessagesDeliveryProof;
|
||||
|
||||
fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> {
|
||||
messages::source::verify_chain_message::<WithMillauMessageBridge>(payload)
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl SourceHeaderChain<bp_millau::Balance> for Millau {
|
||||
type Error = &'static str;
|
||||
// The proof is:
|
||||
// - hash of the header this proof has been created with;
|
||||
// - the storage proof of one or several keys;
|
||||
// - id of the lane we prove messages for;
|
||||
// - inclusive range of messages nonces that are proved.
|
||||
type MessagesProof = FromMillauMessagesProof;
|
||||
|
||||
fn verify_messages_proof(
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rialto -> Millau message lane pallet parameters.
|
||||
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)]
|
||||
pub enum RialtoToMillauMessagesParameter {
|
||||
/// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`.
|
||||
MillauToRialtoConversionRate(FixedU128),
|
||||
}
|
||||
|
||||
impl MessagesParameter for RialtoToMillauMessagesParameter {
|
||||
fn save(&self) {
|
||||
match *self {
|
||||
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => {
|
||||
MillauToRialtoConversionRate::set(conversion_rate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION};
|
||||
use bp_message_dispatch::CallOrigin;
|
||||
use bp_messages::{
|
||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||
MessageKey,
|
||||
};
|
||||
use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount};
|
||||
use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload};
|
||||
use frame_support::{
|
||||
traits::Currency,
|
||||
weights::{GetDispatchInfo, WeightToFeePolynomial},
|
||||
};
|
||||
use sp_runtime::traits::Convert;
|
||||
|
||||
#[test]
|
||||
fn transfer_happens_when_dispatch_fee_is_paid_at_target_chain() {
|
||||
// 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();
|
||||
ext.execute_with(|| {
|
||||
let bridge = MILLAU_CHAIN_ID;
|
||||
let call: Call = SystemCall::remark(vec![]).into();
|
||||
let dispatch_weight = call.get_dispatch_info().weight;
|
||||
let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(&dispatch_weight);
|
||||
assert!(dispatch_fee > 0);
|
||||
|
||||
// create relayer account with minimal balance
|
||||
let relayer_account: AccountId = [1u8; 32].into();
|
||||
let initial_amount = ExistentialDeposit::get();
|
||||
let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||
&relayer_account,
|
||||
initial_amount,
|
||||
);
|
||||
|
||||
// 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 =
|
||||
<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,
|
||||
);
|
||||
|
||||
// dispatch message with intention to pay dispatch fee at the target chain
|
||||
FromMillauMessageDispatch::dispatch(
|
||||
&relayer_account,
|
||||
DispatchMessage {
|
||||
key: MessageKey {
|
||||
lane_id: Default::default(),
|
||||
nonce: 0,
|
||||
},
|
||||
data: DispatchMessageData {
|
||||
payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> {
|
||||
spec_version: VERSION.spec_version,
|
||||
weight: dispatch_weight,
|
||||
origin: CallOrigin::SourceRoot,
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
call: FromBridgedChainEncodedMessageCall::new(call.encode()),
|
||||
}),
|
||||
fee: 1,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// ensure that fee has been transferred from dispatch to relayer account
|
||||
assert_eq!(
|
||||
<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),
|
||||
initial_amount,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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_value(),
|
||||
min_gas_limit: 0x1388.into(),
|
||||
max_gas_limit: U256::max_value(),
|
||||
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