mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Remove unused PoA<>Substrate bridge (#1210)
* Decouple the PoA bridge code from Rialto
* Remove Rialto PoA bridge code
* Remove relays/bin-ethereum code
* Remove relays/client-ethereum code
* Remove modules/ethereum code
* Remove modules/ethereum-contract-builtin code
* Remove PoA bridge documentation
* Remove primitives/ethereum-poa code
* Decouple Rialto from currency-exchange
* Fix building with runtime-benchmarks
* Fix should_encode_bridge_send_message_call test
Because we removed some runtime modules/pallets, the
substrate2substrate bridge pallet has a different index within
the runtime so its calls have a different encoding.
Update the test to use the new encoding.
* Update readme - no more PoA bridge
* Remove deployments/bridges/poa-rialto
Also removes:
- deployments/networks/eth-poa.yml
- deployments/networks/OpenEthereum.Dockerfile
* Remove deployments/dev/poa-config
* Update deployments readme - no more PoA bridge
* Remove eth-related scripts
Deletes:
- deployments/networks/eth-poa.yml
- scripts/run-openethereum-node.sh
* Remove poa-relay from gitlab-ci
* Dockerfiles to use substrate-relay as default
* Remove modules/currency-exchange code
* Remove primitives/currency-exchange code
Signed-off-by: acatangiu <adrian@parity.io>
This commit is contained in:
committed by
Bastian Köcher
parent
2d05583b15
commit
57f3f36cb1
@@ -17,9 +17,9 @@
|
||||
use bp_rialto::derive_account_from_millau_id;
|
||||
use polkadot_primitives::v1::{AssignmentId, ValidatorId};
|
||||
use rialto_runtime::{
|
||||
AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig,
|
||||
BridgeRialtoPoaConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig,
|
||||
SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
|
||||
AccountId, BabeConfig, BalancesConfig, BridgeMillauMessagesConfig, ConfigurationConfig,
|
||||
GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig,
|
||||
WASM_BINARY,
|
||||
};
|
||||
use serde_json::json;
|
||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
@@ -216,8 +216,6 @@ fn testnet_genesis(
|
||||
authorities: Vec::new(),
|
||||
epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG),
|
||||
},
|
||||
bridge_rialto_poa: load_rialto_poa_bridge_config(),
|
||||
bridge_kovan: load_kovan_bridge_config(),
|
||||
grandpa: GrandpaConfig { authorities: Vec::new() },
|
||||
sudo: SudoConfig { key: root_key },
|
||||
session: SessionConfig {
|
||||
@@ -291,22 +289,6 @@ fn testnet_genesis(
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_dave_account_is_as_expected() {
|
||||
let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
|
||||
|
||||
@@ -17,8 +17,6 @@ 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 }
|
||||
@@ -26,9 +24,7 @@ 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 }
|
||||
@@ -80,8 +76,6 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-currency-exchange/std",
|
||||
"bp-eth-poa/std",
|
||||
"bp-header-chain/std",
|
||||
"bp-message-dispatch/std",
|
||||
"bp-messages/std",
|
||||
@@ -99,9 +93,7 @@ std = [
|
||||
"pallet-authority-discovery/std",
|
||||
"pallet-babe/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",
|
||||
@@ -137,8 +129,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,38 +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,259 +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 scale_info::TypeInfo;
|
||||
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, TypeInfo)]
|
||||
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, TypeInfo)]
|
||||
pub struct EthereumTransactionTag {
|
||||
/// Account that has locked funds.
|
||||
pub account: [u8; 20],
|
||||
/// Lock transaction nonce.
|
||||
pub nonce: sp_core::U256,
|
||||
}
|
||||
|
||||
/// Ethereum 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: 'static>(
|
||||
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 = libsecp256k1::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,201 +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 around 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",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,8 @@
|
||||
#[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 parachains;
|
||||
pub mod rialto_poa;
|
||||
|
||||
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
||||
|
||||
@@ -72,8 +66,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;
|
||||
@@ -253,48 +245,6 @@ impl pallet_babe::Config for Runtime {
|
||||
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_bridge_dispatch::Config for Runtime {
|
||||
type Event = Event;
|
||||
type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
|
||||
@@ -307,68 +257,6 @@ 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;
|
||||
@@ -578,12 +466,6 @@ construct_runtime!(
|
||||
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
|
||||
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
|
||||
|
||||
// Eth-PoA chains bridge modules.
|
||||
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},
|
||||
|
||||
// Millau bridge modules.
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
|
||||
@@ -693,46 +575,6 @@ 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 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)
|
||||
}
|
||||
|
||||
fn finalized_block() -> (u64, bp_eth_poa::H256) {
|
||||
let finalized_block = BridgeKovan::finalized_block();
|
||||
(finalized_block.number, finalized_block.hash)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||
fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) {
|
||||
let header = BridgeMillauGrandpa::best_finalized();
|
||||
@@ -744,18 +586,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,
|
||||
@@ -1028,17 +858,10 @@ impl_runtime_apis! {
|
||||
use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
|
||||
use frame_support::traits::StorageInfoTrait;
|
||||
|
||||
use pallet_bridge_currency_exchange::benchmarking::Pallet as BridgeCurrencyExchangeBench;
|
||||
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
|
||||
|
||||
let mut list = Vec::<BenchmarkList>::new();
|
||||
|
||||
list_benchmark!(list, extra, pallet_bridge_eth_poa, BridgeRialtoPoa);
|
||||
list_benchmark!(
|
||||
list,
|
||||
extra,
|
||||
pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
|
||||
);
|
||||
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithMillauMessagesInstance>);
|
||||
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa);
|
||||
|
||||
@@ -1068,46 +891,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;
|
||||
@@ -1274,13 +1057,6 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa);
|
||||
add_benchmark!(
|
||||
params,
|
||||
batches,
|
||||
pallet_bridge_currency_exchange,
|
||||
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
|
||||
);
|
||||
add_benchmark!(
|
||||
params,
|
||||
batches,
|
||||
@@ -1322,48 +1098,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>;
|
||||
@@ -1405,50 +1141,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[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
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_size() {
|
||||
const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests
|
||||
|
||||
@@ -1,183 +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