mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-09 15:18:00 +00:00
messages bridge between RialtoParachain and Millau (#1218)
This commit is contained in:
committed by
Bastian Köcher
parent
03c2f06a27
commit
5f2f61ced5
@@ -18,8 +18,8 @@ use beefy_primitives::crypto::AuthorityId as BeefyId;
|
||||
use bp_millau::derive_account_from_rialto_id;
|
||||
use millau_runtime::{
|
||||
AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig,
|
||||
BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys,
|
||||
Signature, SudoConfig, SystemConfig, WASM_BINARY,
|
||||
BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig,
|
||||
SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
|
||||
};
|
||||
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
@@ -151,7 +151,7 @@ fn endowed_accounts() -> Vec<AccountId> {
|
||||
get_account_id_from_seed::<sr25519::Public>("George//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Harry//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner"),
|
||||
get_account_id_from_seed::<sr25519::Public>("WithRialtoTokenSwap"),
|
||||
get_account_id_from_seed::<sr25519::Public>("RialtoParachainMessagesOwner"),
|
||||
pallet_bridge_messages::relayer_fund_account_id::<
|
||||
bp_millau::AccountId,
|
||||
bp_millau::AccountIdConverter,
|
||||
@@ -217,6 +217,12 @@ fn testnet_genesis(
|
||||
owner: Some(get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner")),
|
||||
..Default::default()
|
||||
},
|
||||
bridge_rialto_parachain_messages: BridgeRialtoParachainMessagesConfig {
|
||||
owner: Some(get_account_id_from_seed::<sr25519::Public>(
|
||||
"RialtoParachainMessagesOwner",
|
||||
)),
|
||||
..Default::default()
|
||||
},
|
||||
xcm_pallet: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
bp-header-chain = { path = "../../../primitives/header-chain", default-features = false }
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false }
|
||||
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
||||
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
bp-westend = { path = "../../../primitives/chain-westend", default-features = false }
|
||||
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
|
||||
@@ -87,7 +89,9 @@ std = [
|
||||
"bp-header-chain/std",
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-polkadot-core/std",
|
||||
"bp-rialto/std",
|
||||
"bp-rialto-parachain/std",
|
||||
"bp-runtime/std",
|
||||
"bp-westend/std",
|
||||
"bridge-runtime-common/std",
|
||||
|
||||
@@ -29,14 +29,21 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
pub mod rialto_messages;
|
||||
pub mod rialto_parachain_messages;
|
||||
pub mod xcm_config;
|
||||
|
||||
use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge};
|
||||
use crate::{
|
||||
rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge},
|
||||
rialto_parachain_messages::{
|
||||
ToRialtoParachainMessagePayload, WithRialtoParachainMessageBridge,
|
||||
},
|
||||
};
|
||||
|
||||
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
|
||||
use bridge_runtime_common::messages::{
|
||||
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
|
||||
};
|
||||
use codec::Decode;
|
||||
use pallet_grandpa::{
|
||||
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
||||
};
|
||||
@@ -49,7 +56,9 @@ use sp_mmr_primitives::{
|
||||
};
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys,
|
||||
traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys},
|
||||
traits::{
|
||||
Block as BlockT, Header as HeaderT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys,
|
||||
},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill,
|
||||
};
|
||||
@@ -416,6 +425,15 @@ impl pallet_bridge_grandpa::Config<WestendGrandpaInstance> for Runtime {
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight<Runtime>;
|
||||
}
|
||||
|
||||
pub type RialtoParachainGrandpaInstance = pallet_bridge_grandpa::Instance2;
|
||||
impl pallet_bridge_grandpa::Config<RialtoParachainGrandpaInstance> for Runtime {
|
||||
type BridgedChain = bp_rialto_parachain::RialtoParachain;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight<Runtime>;
|
||||
}
|
||||
|
||||
impl pallet_shift_session_manager::Config for Runtime {}
|
||||
|
||||
parameter_types! {
|
||||
@@ -429,6 +447,7 @@ parameter_types! {
|
||||
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
|
||||
pub const RootAccountForPayments: Option<AccountId> = None;
|
||||
pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID;
|
||||
pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID;
|
||||
}
|
||||
|
||||
/// Instance of the messages pallet used to relay messages to/from Rialto chain.
|
||||
@@ -462,6 +481,37 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
|
||||
type BridgedChainId = RialtoChainId;
|
||||
}
|
||||
|
||||
/// Instance of the messages pallet used to relay messages to/from RialtoParachain chain.
|
||||
pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1;
|
||||
|
||||
impl pallet_bridge_messages::Config<WithRialtoParachainMessagesInstance> for Runtime {
|
||||
type Event = Event;
|
||||
type WeightInfo = pallet_bridge_messages::weights::MillauWeight<Runtime>;
|
||||
type Parameter = rialto_parachain_messages::MillauToRialtoParachainMessagesParameter;
|
||||
type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce;
|
||||
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
|
||||
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
|
||||
|
||||
type OutboundPayload = crate::rialto_parachain_messages::ToRialtoParachainMessagePayload;
|
||||
type OutboundMessageFee = Balance;
|
||||
|
||||
type InboundPayload = crate::rialto_parachain_messages::FromRialtoParachainMessagePayload;
|
||||
type InboundMessageFee = bp_rialto_parachain::Balance;
|
||||
type InboundRelayer = bp_rialto_parachain::AccountId;
|
||||
|
||||
type AccountIdConverter = bp_millau::AccountIdConverter;
|
||||
|
||||
type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain;
|
||||
type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain;
|
||||
type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch;
|
||||
type BridgedChainId = RialtoParachainChainId;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME;
|
||||
}
|
||||
@@ -509,8 +559,9 @@ construct_runtime!(
|
||||
// Westend bridge modules.
|
||||
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},
|
||||
|
||||
// Rialto parachains bridge modules.
|
||||
// RialtoParachain bridge modules.
|
||||
BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage},
|
||||
BridgeRialtoParachainMessages: pallet_bridge_messages::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
|
||||
// Pallet for sending XCM.
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 99,
|
||||
@@ -750,6 +801,23 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_rialto_parachain::RialtoParachainFinalityApi<Block> for Runtime {
|
||||
fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) {
|
||||
// the parachains finality pallet is never decoding parachain heads, so it is
|
||||
// only done in the integration code
|
||||
use crate::rialto_parachain_messages::RIALTO_PARACHAIN_ID;
|
||||
let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::<
|
||||
Runtime,
|
||||
WitRialtoParachainsInstance,
|
||||
>::best_parachain_head(RIALTO_PARACHAIN_ID.into())
|
||||
.and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok());
|
||||
match best_rialto_parachain_head {
|
||||
Some(head) => (*head.number(), head.hash()),
|
||||
None => (Default::default(), Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_rialto::ToRialtoOutboundLaneApi<Block, Balance, ToRialtoMessagePayload> for Runtime {
|
||||
fn estimate_message_delivery_and_dispatch_fee(
|
||||
_lane_id: bp_messages::LaneId,
|
||||
@@ -777,6 +845,33 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi<Block, Balance, ToRialtoParachainMessagePayload> for Runtime {
|
||||
fn estimate_message_delivery_and_dispatch_fee(
|
||||
_lane_id: bp_messages::LaneId,
|
||||
payload: ToRialtoParachainMessagePayload,
|
||||
rialto_parachain_to_this_conversion_rate: Option<FixedU128>,
|
||||
) -> Option<Balance> {
|
||||
estimate_message_dispatch_and_delivery_fee::<WithRialtoParachainMessageBridge>(
|
||||
&payload,
|
||||
WithRialtoParachainMessageBridge::RELAYER_FEE_PERCENT,
|
||||
rialto_parachain_to_this_conversion_rate,
|
||||
).ok()
|
||||
}
|
||||
|
||||
fn message_details(
|
||||
lane: bp_messages::LaneId,
|
||||
begin: bp_messages::MessageNonce,
|
||||
end: bp_messages::MessageNonce,
|
||||
) -> Vec<bp_messages::MessageDetails<Balance>> {
|
||||
bridge_runtime_common::messages_api::outbound_message_details::<
|
||||
Runtime,
|
||||
WithRialtoParachainMessagesInstance,
|
||||
WithRialtoParachainMessageBridge,
|
||||
xcm_config::OutboundXcmWeigher,
|
||||
>(lane, begin, end)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl frame_benchmarking::Benchmark<Block> for Runtime {
|
||||
fn benchmark_metadata(extra: bool) -> (
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// 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 <-> RialtoParachain messages.
|
||||
|
||||
use crate::Runtime;
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::{SenderOrigin, TargetHeaderChain},
|
||||
target_chain::{ProvedMessages, SourceHeaderChain},
|
||||
InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter,
|
||||
};
|
||||
use bp_polkadot_core::parachains::ParaId;
|
||||
use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID};
|
||||
use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
weights::{DispatchClass, Weight},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
|
||||
use sp_std::convert::TryFrom;
|
||||
|
||||
/// Identifier of RialtoParachain in the Rialto relay chain.
|
||||
///
|
||||
/// This identifier is not something that is declared either by Rialto or RialtoParachain. This
|
||||
/// is an identifier of registration. So in theory it may be changed. But since bridge is going
|
||||
/// to be deployed after parachain registration AND since parachain de-registration is highly
|
||||
/// likely impossible, it is fine to declare this constant here.
|
||||
pub const RIALTO_PARACHAIN_ID: u32 = 2000;
|
||||
/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge
|
||||
/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual
|
||||
/// tests, confirming that we don't break encoding somewhere between.
|
||||
pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT;
|
||||
|
||||
/// Initial value of `RialtoParachainToMillauConversionRate` parameter.
|
||||
pub const INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE: FixedU128 =
|
||||
FixedU128::from_inner(FixedU128::DIV);
|
||||
/// Initial value of `RialtoParachainFeeMultiplier` parameter.
|
||||
pub const INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER: FixedU128 =
|
||||
FixedU128::from_inner(FixedU128::DIV);
|
||||
|
||||
parameter_types! {
|
||||
/// RialtoParachain to Millau conversion rate. Initially we treat both tokens as equal.
|
||||
pub storage RialtoParachainToMillauConversionRate: FixedU128 = INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE;
|
||||
/// Fee multiplier value at RialtoParachain chain.
|
||||
pub storage RialtoParachainFeeMultiplier: FixedU128 = INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
/// Message payload for Millau -> RialtoParachain messages.
|
||||
pub type ToRialtoParachainMessagePayload = messages::source::FromThisChainMessagePayload;
|
||||
|
||||
/// Message verifier for Millau -> RialtoParachain messages.
|
||||
pub type ToRialtoParachainMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithRialtoParachainMessageBridge>;
|
||||
|
||||
/// Message payload for RialtoParachain -> Millau messages.
|
||||
pub type FromRialtoParachainMessagePayload =
|
||||
messages::target::FromBridgedChainMessagePayload<crate::Call>;
|
||||
|
||||
/// Messages proof for RialtoParachain -> Millau messages.
|
||||
type FromRialtoParachainMessagesProof =
|
||||
messages::target::FromBridgedChainMessagesProof<bp_rialto_parachain::Hash>;
|
||||
|
||||
/// Messages delivery proof for Millau -> RialtoParachain messages.
|
||||
type ToRialtoParachainMessagesDeliveryProof =
|
||||
messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto_parachain::Hash>;
|
||||
|
||||
/// Call-dispatch based message dispatch for RialtoParachain -> Millau messages.
|
||||
pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
||||
WithRialtoParachainMessageBridge,
|
||||
xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>,
|
||||
crate::xcm_config::XcmWeigher,
|
||||
// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge
|
||||
// (it is prepended with `UniversalOrigin` instruction)
|
||||
frame_support::traits::ConstU64<BASE_XCM_WEIGHT_TWICE>,
|
||||
>;
|
||||
|
||||
/// Millau <-> RialtoParachain message bridge.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct WithRialtoParachainMessageBridge;
|
||||
|
||||
impl MessageBridge for WithRialtoParachainMessageBridge {
|
||||
const RELAYER_FEE_PERCENT: u32 = 10;
|
||||
const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
|
||||
const BRIDGED_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID;
|
||||
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME;
|
||||
|
||||
type ThisChain = Millau;
|
||||
type BridgedChain = RialtoParachain;
|
||||
|
||||
fn bridged_balance_to_this_balance(
|
||||
bridged_balance: bp_rialto_parachain::Balance,
|
||||
bridged_to_this_conversion_rate_override: Option<FixedU128>,
|
||||
) -> bp_millau::Balance {
|
||||
let conversion_rate = bridged_to_this_conversion_rate_override
|
||||
.unwrap_or_else(|| RialtoParachainToMillauConversionRate::get());
|
||||
bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance))
|
||||
.unwrap_or(bp_millau::Balance::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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::ThisChainWithMessages for Millau {
|
||||
type Call = crate::Call;
|
||||
type Origin = crate::Origin;
|
||||
|
||||
fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool {
|
||||
(*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) && send_origin.linked_account().is_some()
|
||||
}
|
||||
|
||||
fn maximal_pending_messages_at_outbound_lane() -> MessageNonce {
|
||||
MessageNonce::MAX
|
||||
}
|
||||
|
||||
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
||||
let inbound_data_size = InboundLaneData::<bp_millau::AccountId>::encoded_size_hint(
|
||||
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
.unwrap_or(u32::MAX);
|
||||
|
||||
MessageTransaction {
|
||||
dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||
size: inbound_data_size
|
||||
.saturating_add(bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_millau::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
|
||||
// `transaction` may represent transaction from the future, when multiplier value will
|
||||
// be larger, so let's use slightly increased value
|
||||
let multiplier = FixedU128::saturating_from_rational(110, 100)
|
||||
.saturating_mul(pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier());
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
|
||||
1,
|
||||
multiplier,
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// RialtoParachain chain from message lane point of view.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct RialtoParachain;
|
||||
|
||||
impl messages::ChainWithMessages for RialtoParachain {
|
||||
type Hash = bp_rialto_parachain::Hash;
|
||||
type AccountId = bp_rialto_parachain::AccountId;
|
||||
type Signer = bp_rialto_parachain::AccountSigner;
|
||||
type Signature = bp_rialto_parachain::Signature;
|
||||
type Weight = Weight;
|
||||
type Balance = bp_rialto_parachain::Balance;
|
||||
}
|
||||
|
||||
impl messages::BridgedChainWithMessages for RialtoParachain {
|
||||
fn maximal_extrinsic_size() -> u32 {
|
||||
bp_rialto_parachain::RialtoParachain::max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
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_rialto_parachain::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
||||
.saturating_add(bp_rialto_parachain::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
||||
.saturating_sub(if include_pay_dispatch_fee_cost {
|
||||
0
|
||||
} else {
|
||||
bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT
|
||||
})
|
||||
.saturating_add(message_dispatch_weight),
|
||||
size: message_payload_len
|
||||
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(
|
||||
transaction: MessageTransaction<Weight>,
|
||||
) -> bp_rialto_parachain::Balance {
|
||||
// we don't have a direct access to the value of multiplier at RialtoParachain chain
|
||||
// => it is a messages module parameter
|
||||
let multiplier = RialtoParachainFeeMultiplier::get();
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_rialto_parachain::BlockWeights::get()
|
||||
.get(DispatchClass::Normal)
|
||||
.base_extrinsic,
|
||||
1,
|
||||
multiplier,
|
||||
|weight| weight as _,
|
||||
transaction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetHeaderChain<ToRialtoParachainMessagePayload, bp_rialto_parachain::AccountId>
|
||||
for RialtoParachain
|
||||
{
|
||||
type Error = &'static str;
|
||||
// The proof is:
|
||||
// - hash of the header this proof has been created with;
|
||||
// - the storage proof or one or several keys;
|
||||
// - id of the lane we prove state of.
|
||||
type MessagesDeliveryProof = ToRialtoParachainMessagesDeliveryProof;
|
||||
|
||||
fn verify_message(payload: &ToRialtoParachainMessagePayload) -> Result<(), Self::Error> {
|
||||
messages::source::verify_chain_message::<WithRialtoParachainMessageBridge>(payload)
|
||||
}
|
||||
|
||||
fn verify_messages_delivery_proof(
|
||||
proof: Self::MessagesDeliveryProof,
|
||||
) -> Result<(LaneId, InboundLaneData<bp_millau::AccountId>), Self::Error> {
|
||||
messages::source::verify_messages_delivery_proof_from_parachain::<
|
||||
WithRialtoParachainMessageBridge,
|
||||
bp_rialto_parachain::Header,
|
||||
Runtime,
|
||||
crate::WitRialtoParachainsInstance,
|
||||
>(ParaId(RIALTO_PARACHAIN_ID), proof)
|
||||
}
|
||||
}
|
||||
|
||||
impl SourceHeaderChain<bp_rialto_parachain::Balance> for RialtoParachain {
|
||||
type Error = &'static str;
|
||||
// The proof is:
|
||||
// - hash of the header this proof has been created with;
|
||||
// - the storage proof or one or several keys;
|
||||
// - id of the lane we prove messages for;
|
||||
// - inclusive range of messages nonces that are proved.
|
||||
type MessagesProof = FromRialtoParachainMessagesProof;
|
||||
|
||||
fn verify_messages_proof(
|
||||
proof: Self::MessagesProof,
|
||||
messages_count: u32,
|
||||
) -> Result<ProvedMessages<Message<bp_rialto_parachain::Balance>>, Self::Error> {
|
||||
messages::target::verify_messages_proof_from_parachain::<
|
||||
WithRialtoParachainMessageBridge,
|
||||
bp_rialto_parachain::Header,
|
||||
Runtime,
|
||||
crate::WitRialtoParachainsInstance,
|
||||
>(ParaId(RIALTO_PARACHAIN_ID), proof, messages_count)
|
||||
}
|
||||
}
|
||||
|
||||
/// Millau -> RialtoParachain message lane pallet parameters.
|
||||
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
|
||||
pub enum MillauToRialtoParachainMessagesParameter {
|
||||
/// The conversion formula we use is: `MillauTokens = RialtoParachainTokens * conversion_rate`.
|
||||
RialtoParachainToMillauConversionRate(FixedU128),
|
||||
}
|
||||
|
||||
impl MessagesParameter for MillauToRialtoParachainMessagesParameter {
|
||||
fn save(&self) {
|
||||
match *self {
|
||||
MillauToRialtoParachainMessagesParameter::RialtoParachainToMillauConversionRate(
|
||||
ref conversion_rate,
|
||||
) => RialtoParachainToMillauConversionRate::set(conversion_rate),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,11 @@ codec = { package = 'parity-scale-codec', version = '3.0.0' }
|
||||
serde = { version = '1.0', features = ['derive'] }
|
||||
hex-literal = '0.3.1'
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain" }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages" }
|
||||
|
||||
# RPC related Dependencies
|
||||
jsonrpc-core = '18.0'
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ pub fn development_config(id: ParaId) -> ChainSpec {
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
||||
pallet_bridge_messages::relayer_fund_account_id::<
|
||||
bp_rialto_parachain::AccountId,
|
||||
bp_rialto_parachain::AccountIdConverter,
|
||||
>(),
|
||||
],
|
||||
id,
|
||||
)
|
||||
@@ -126,6 +130,10 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec {
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
||||
pallet_bridge_messages::relayer_fund_account_id::<
|
||||
bp_rialto_parachain::AccountId,
|
||||
bp_rialto_parachain::AccountIdConverter,
|
||||
>(),
|
||||
],
|
||||
id,
|
||||
)
|
||||
@@ -161,6 +169,7 @@ fn testnet_genesis(
|
||||
parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id },
|
||||
aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities },
|
||||
aura_ext: Default::default(),
|
||||
bridge_millau_messages: Default::default(),
|
||||
// parachain_system: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@ serde = { version = '1.0', optional = true, features = ['derive'] }
|
||||
|
||||
# Bridge depedencies
|
||||
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
|
||||
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
## Substrate Primitive Dependencies
|
||||
@@ -82,7 +88,11 @@ runtime-benchmarks = [
|
||||
'pallet-timestamp/runtime-benchmarks',
|
||||
]
|
||||
std = [
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-runtime/std",
|
||||
"bp-rialto-parachain/std",
|
||||
"bridge-runtime-common/std",
|
||||
"codec/std",
|
||||
"log/std",
|
||||
"scale-info/std",
|
||||
@@ -102,6 +112,8 @@ std = [
|
||||
"frame-executive/std",
|
||||
"frame-system/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-randomness-collective-flip/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-sudo/std",
|
||||
|
||||
@@ -26,13 +26,18 @@
|
||||
#[cfg(feature = "std")]
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
||||
|
||||
use bridge_runtime_common::messages::{
|
||||
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
|
||||
};
|
||||
use sp_api::impl_runtime_apis;
|
||||
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys,
|
||||
traits::{AccountIdLookup, Block as BlockT},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult,
|
||||
ApplyExtrinsicResult, FixedU128,
|
||||
};
|
||||
|
||||
use sp_std::prelude::*;
|
||||
@@ -52,6 +57,7 @@ pub use frame_support::{
|
||||
};
|
||||
pub use frame_system::{Call as SystemCall, EnsureRoot};
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
pub use pallet_sudo::Call as SudoCall;
|
||||
pub use pallet_timestamp::Call as TimestampCall;
|
||||
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
@@ -63,6 +69,9 @@ pub use bp_rialto_parachain::{
|
||||
Index, Signature, MAXIMUM_BLOCK_WEIGHT,
|
||||
};
|
||||
|
||||
pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall;
|
||||
pub use pallet_bridge_messages::Call as MessagesCall;
|
||||
|
||||
// Polkadot & XCM imports
|
||||
use pallet_xcm::XcmPassthrough;
|
||||
use polkadot_parachain::primitives::Sibling;
|
||||
@@ -76,6 +85,8 @@ use xcm_builder::{
|
||||
};
|
||||
use xcm_executor::{Config, XcmExecutor};
|
||||
|
||||
mod millau_messages;
|
||||
|
||||
/// The address format for describing accounts.
|
||||
pub type Address = MultiAddress<AccountId, ()>;
|
||||
/// Block type as expected by this runtime.
|
||||
@@ -88,6 +99,7 @@ pub type BlockId = generic::BlockId<Block>;
|
||||
pub type SignedExtra = (
|
||||
frame_system::CheckNonZeroSender<Runtime>,
|
||||
frame_system::CheckSpecVersion<Runtime>,
|
||||
frame_system::CheckTxVersion<Runtime>,
|
||||
frame_system::CheckGenesis<Runtime>,
|
||||
frame_system::CheckEra<Runtime>,
|
||||
frame_system::CheckNonce<Runtime>,
|
||||
@@ -342,9 +354,11 @@ pub type XcmOriginToTransactDispatchOrigin = (
|
||||
XcmPassthrough<Origin>,
|
||||
);
|
||||
|
||||
pub const BASE_XCM_WEIGHT: Weight = 1_000_000;
|
||||
|
||||
parameter_types! {
|
||||
// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
|
||||
pub UnitWeightCost: Weight = 1_000_000;
|
||||
pub UnitWeightCost: Weight = BASE_XCM_WEIGHT;
|
||||
// One UNIT buys 1 second of weight.
|
||||
pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT);
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
@@ -366,6 +380,11 @@ pub type Barrier = (
|
||||
// ^^^ Parent & its unit plurality gets free execution
|
||||
);
|
||||
|
||||
/// Outbound XCM weigher type.
|
||||
pub type OutboundXcmWeigher = FixedWeightBounds<UnitWeightCost, (), MaxInstructions>;
|
||||
/// XCM weigher type.
|
||||
pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
|
||||
|
||||
pub struct XcmConfig;
|
||||
impl Config for XcmConfig {
|
||||
type Call = Call;
|
||||
@@ -376,7 +395,7 @@ impl Config for XcmConfig {
|
||||
type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT
|
||||
type UniversalLocation = UniversalLocation;
|
||||
type Barrier = Barrier;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
|
||||
type Weigher = XcmWeigher;
|
||||
type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;
|
||||
type ResponseHandler = PolkadotXcm;
|
||||
type AssetTrap = PolkadotXcm;
|
||||
@@ -412,7 +431,7 @@ impl pallet_xcm::Config for Runtime {
|
||||
type XcmExecutor = XcmExecutor<XcmConfig>;
|
||||
type XcmTeleportFilter = Everything;
|
||||
type XcmReserveTransferFilter = Everything;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
|
||||
type Weigher = XcmWeigher;
|
||||
type Origin = Origin;
|
||||
type Call = Call;
|
||||
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
|
||||
@@ -454,10 +473,71 @@ impl pallet_aura::Config for Runtime {
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
}
|
||||
|
||||
// /// Configure the pallet template in pallets/template.
|
||||
// impl template::Config for Runtime {
|
||||
// type Event = Event;
|
||||
// }
|
||||
parameter_types! {
|
||||
/// This is a pretty unscientific cap.
|
||||
///
|
||||
/// Note that once this is hit the pallet will essentially throttle incoming requests down to one
|
||||
/// call per block.
|
||||
pub const MaxRequests: u32 = 50;
|
||||
|
||||
/// Number of headers to keep.
|
||||
///
|
||||
/// Assuming the worst case of every header being finalized, we will keep headers at least for a
|
||||
/// week.
|
||||
pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32;
|
||||
}
|
||||
|
||||
pub type MillauGrandpaInstance = ();
|
||||
impl pallet_bridge_grandpa::Config for Runtime {
|
||||
type BridgedChain = bp_millau::Millau;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8;
|
||||
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
|
||||
bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
||||
bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
// `IdentityFee` is used by Rialto => we may use weight directly
|
||||
pub const GetDeliveryConfirmationTransactionFee: Balance =
|
||||
bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
|
||||
pub const RootAccountForPayments: Option<AccountId> = None;
|
||||
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID;
|
||||
}
|
||||
|
||||
/// Instance of the messages pallet used to relay messages to/from Millau chain.
|
||||
pub type WithMillauMessagesInstance = ();
|
||||
|
||||
impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
||||
type Event = Event;
|
||||
type WeightInfo = pallet_bridge_messages::weights::MillauWeight<Runtime>;
|
||||
type Parameter = millau_messages::RialtoParachainToMillauMessagesParameter;
|
||||
type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce;
|
||||
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
|
||||
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
|
||||
|
||||
type OutboundPayload = crate::millau_messages::ToMillauMessagePayload;
|
||||
type OutboundMessageFee = Balance;
|
||||
|
||||
type InboundPayload = crate::millau_messages::FromMillauMessagePayload;
|
||||
type InboundMessageFee = bp_millau::Balance;
|
||||
type InboundRelayer = bp_millau::AccountId;
|
||||
|
||||
type AccountIdConverter = bp_rialto_parachain::AccountIdConverter;
|
||||
|
||||
type TargetHeaderChain = crate::millau_messages::Millau;
|
||||
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
type SourceHeaderChain = crate::millau_messages::Millau;
|
||||
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
|
||||
type BridgedChainId = BridgedChainId;
|
||||
}
|
||||
|
||||
// Create the runtime by composing the FRAME pallets that were previously configured.
|
||||
construct_runtime!(
|
||||
@@ -486,8 +566,9 @@ construct_runtime!(
|
||||
CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
|
||||
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
|
||||
|
||||
// //Template
|
||||
// TemplatePallet: template::{Pallet, Call, Storage, Event<T>},
|
||||
// Millau bridge modules.
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -600,6 +681,40 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||
fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) {
|
||||
let header = BridgeMillauGrandpa::best_finalized();
|
||||
(header.number, header.hash())
|
||||
}
|
||||
}
|
||||
|
||||
impl bp_millau::ToMillauOutboundLaneApi<Block, Balance, ToMillauMessagePayload> for Runtime {
|
||||
fn estimate_message_delivery_and_dispatch_fee(
|
||||
_lane_id: bp_messages::LaneId,
|
||||
payload: ToMillauMessagePayload,
|
||||
millau_to_this_conversion_rate: Option<FixedU128>,
|
||||
) -> Option<Balance> {
|
||||
estimate_message_dispatch_and_delivery_fee::<WithMillauMessageBridge>(
|
||||
&payload,
|
||||
WithMillauMessageBridge::RELAYER_FEE_PERCENT,
|
||||
millau_to_this_conversion_rate,
|
||||
).ok()
|
||||
}
|
||||
|
||||
fn message_details(
|
||||
lane: bp_messages::LaneId,
|
||||
begin: bp_messages::MessageNonce,
|
||||
end: bp_messages::MessageNonce,
|
||||
) -> Vec<bp_messages::MessageDetails<Balance>> {
|
||||
bridge_runtime_common::messages_api::outbound_message_details::<
|
||||
Runtime,
|
||||
WithMillauMessagesInstance,
|
||||
WithMillauMessageBridge,
|
||||
OutboundXcmWeigher,
|
||||
>(lane, begin, end)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl frame_benchmarking::Benchmark<Block> for Runtime {
|
||||
fn dispatch_benchmark(
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// 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 <-> RialtoParachain messages.
|
||||
|
||||
// TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime.
|
||||
// Should be extracted to a separate crate and reused here.
|
||||
|
||||
use crate::Runtime;
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::{SenderOrigin, TargetHeaderChain},
|
||||
target_chain::{ProvedMessages, SourceHeaderChain},
|
||||
InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter,
|
||||
};
|
||||
use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID};
|
||||
use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
weights::{DispatchClass, Weight},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
|
||||
use sp_std::convert::TryFrom;
|
||||
|
||||
/// Initial value of `MillauToRialtoParachainConversionRate` parameter.
|
||||
pub const INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE: FixedU128 =
|
||||
FixedU128::from_inner(FixedU128::DIV);
|
||||
/// Initial value of `MillauFeeMultiplier` parameter.
|
||||
pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV);
|
||||
/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge
|
||||
/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual
|
||||
/// tests, confirming that we don't break encoding somewhere between.
|
||||
pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::BASE_XCM_WEIGHT;
|
||||
|
||||
parameter_types! {
|
||||
/// Millau to RialtoParachain conversion rate. Initially we treat both tokens as equal.
|
||||
pub storage MillauToRialtoParachainConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE;
|
||||
/// Fee multiplier value at Millau chain.
|
||||
pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
/// Message payload for RialtoParachain -> Millau messages.
|
||||
pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload;
|
||||
|
||||
/// Message verifier for RialtoParachain -> Millau messages.
|
||||
pub type ToMillauMessageVerifier =
|
||||
messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
|
||||
|
||||
/// Message payload for Millau -> RialtoParachain messages.
|
||||
pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<crate::Call>;
|
||||
|
||||
/// Call-dispatch based message dispatch for Millau -> RialtoParachain messages.
|
||||
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
||||
WithMillauMessageBridge,
|
||||
xcm_executor::XcmExecutor<crate::XcmConfig>,
|
||||
crate::XcmWeigher,
|
||||
// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge
|
||||
// (it is prepended with `UniversalOrigin` instruction)
|
||||
frame_support::traits::ConstU64<BASE_XCM_WEIGHT_TWICE>,
|
||||
>;
|
||||
|
||||
/// Messages proof for Millau -> RialtoParachain messages.
|
||||
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
|
||||
|
||||
/// Messages delivery proof for RialtoParachain -> Millau messages.
|
||||
pub type ToMillauMessagesDeliveryProof =
|
||||
messages::source::FromBridgedChainMessagesDeliveryProof<bp_millau::Hash>;
|
||||
|
||||
/// Millau <-> RialtoParachain 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_PARACHAIN_CHAIN_ID;
|
||||
const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
|
||||
const BRIDGED_MESSAGES_PALLET_NAME: &'static str =
|
||||
bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME;
|
||||
|
||||
type ThisChain = RialtoParachain;
|
||||
type BridgedChain = Millau;
|
||||
|
||||
fn bridged_balance_to_this_balance(
|
||||
bridged_balance: bp_millau::Balance,
|
||||
bridged_to_this_conversion_rate_override: Option<FixedU128>,
|
||||
) -> bp_rialto_parachain::Balance {
|
||||
let conversion_rate = bridged_to_this_conversion_rate_override
|
||||
.unwrap_or_else(|| MillauToRialtoParachainConversionRate::get());
|
||||
bp_rialto_parachain::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance))
|
||||
.unwrap_or(bp_rialto_parachain::Balance::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
/// RialtoParachain chain from message lane point of view.
|
||||
#[derive(RuntimeDebug, Clone, Copy)]
|
||||
pub struct RialtoParachain;
|
||||
|
||||
impl messages::ChainWithMessages for RialtoParachain {
|
||||
type Hash = bp_rialto_parachain::Hash;
|
||||
type AccountId = bp_rialto_parachain::AccountId;
|
||||
type Signer = bp_rialto_parachain::AccountSigner;
|
||||
type Signature = bp_rialto_parachain::Signature;
|
||||
type Weight = Weight;
|
||||
type Balance = bp_rialto_parachain::Balance;
|
||||
}
|
||||
|
||||
impl messages::ThisChainWithMessages for RialtoParachain {
|
||||
type Call = crate::Call;
|
||||
type Origin = crate::Origin;
|
||||
|
||||
fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool {
|
||||
send_origin.linked_account().is_some() && (*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_parachain::AccountId>::encoded_size_hint(
|
||||
bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
.unwrap_or(u32::MAX);
|
||||
|
||||
MessageTransaction {
|
||||
dispatch_weight:
|
||||
bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||
size: inbound_data_size
|
||||
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(
|
||||
transaction: MessageTransaction<Weight>,
|
||||
) -> bp_rialto_parachain::Balance {
|
||||
// `transaction` may represent transaction from the future, when multiplier value will
|
||||
// be larger, so let's use slightly increased value
|
||||
let multiplier = FixedU128::saturating_from_rational(110, 100)
|
||||
.saturating_mul(pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier());
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_rialto_parachain::BlockWeights::get()
|
||||
.get(DispatchClass::Normal)
|
||||
.base_extrinsic,
|
||||
1,
|
||||
multiplier,
|
||||
|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::Millau::max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
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_parachain::EXTRA_STORAGE_PROOF_SIZE)
|
||||
.saturating_add(bp_millau::TX_EXTRA_BYTES),
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
|
||||
// we don't have a direct access to the value of multiplier at Millau chain
|
||||
// => it is a messages module parameter
|
||||
let multiplier = MillauFeeMultiplier::get();
|
||||
// in our testnets, both per-byte fee and weight-to-fee are 1:1
|
||||
messages::transaction_payment(
|
||||
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
|
||||
1,
|
||||
multiplier,
|
||||
|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_parachain::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)
|
||||
}
|
||||
}
|
||||
|
||||
impl SenderOrigin<crate::AccountId> for crate::Origin {
|
||||
fn linked_account(&self) -> Option<crate::AccountId> {
|
||||
match self.caller {
|
||||
crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) =>
|
||||
Some(submitter.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// RialtoParachain -> Millau message lane pallet parameters.
|
||||
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
|
||||
pub enum RialtoParachainToMillauMessagesParameter {
|
||||
/// The conversion formula we use is: `RialtoParachainTokens = MillauTokens * conversion_rate`.
|
||||
MillauToRialtoParachainConversionRate(FixedU128),
|
||||
}
|
||||
|
||||
impl MessagesParameter for RialtoParachainToMillauMessagesParameter {
|
||||
fn save(&self) {
|
||||
match *self {
|
||||
RialtoParachainToMillauMessagesParameter::MillauToRialtoParachainConversionRate(
|
||||
ref conversion_rate,
|
||||
) => MillauToRialtoParachainConversionRate::set(conversion_rate),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,7 +425,7 @@ parameter_types! {
|
||||
pub const GetDeliveryConfirmationTransactionFee: Balance =
|
||||
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
|
||||
pub const RootAccountForPayments: Option<AccountId> = None;
|
||||
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID;
|
||||
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID;
|
||||
}
|
||||
|
||||
/// Instance of the messages pallet used to relay messages to/from Millau chain.
|
||||
|
||||
@@ -18,9 +18,11 @@ static_assertions = { version = "1.1", optional = true }
|
||||
# Bridge dependencies
|
||||
|
||||
bp-messages = { path = "../../primitives/messages", default-features = false }
|
||||
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
|
||||
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
|
||||
pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false }
|
||||
|
||||
# Substrate dependencies
|
||||
|
||||
@@ -47,6 +49,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-x
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-messages/std",
|
||||
"bp-polkadot-core/std",
|
||||
"bp-runtime/std",
|
||||
"codec/std",
|
||||
"frame-support/std",
|
||||
@@ -56,6 +59,7 @@ std = [
|
||||
"num-traits/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-bridge-parachains/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"scale-info/std",
|
||||
"sp-api/std",
|
||||
|
||||
@@ -25,13 +25,14 @@ use bp_messages::{
|
||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages},
|
||||
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
||||
};
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaId};
|
||||
use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker};
|
||||
use codec::{Decode, DecodeLimit, Encode};
|
||||
use frame_support::{traits::Get, weights::Weight, RuntimeDebug};
|
||||
use hash_db::Hasher;
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul},
|
||||
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Header as HeaderT},
|
||||
FixedPointNumber, FixedPointOperand, FixedU128,
|
||||
};
|
||||
use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec};
|
||||
@@ -390,6 +391,9 @@ pub mod source {
|
||||
}
|
||||
|
||||
/// Verify proof of This -> Bridged chain messages delivery.
|
||||
///
|
||||
/// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged
|
||||
/// parachains, please use the `verify_messages_delivery_proof_from_parachain`.
|
||||
pub fn verify_messages_delivery_proof<B: MessageBridge, ThisRuntime, GrandpaInstance: 'static>(
|
||||
proof: FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain<B>>>,
|
||||
) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str>
|
||||
@@ -406,23 +410,70 @@ pub mod source {
|
||||
pallet_bridge_grandpa::Pallet::<ThisRuntime, GrandpaInstance>::parse_finalized_storage_proof(
|
||||
bridged_header_hash.into(),
|
||||
StorageProof::new(storage_proof),
|
||||
|storage| {
|
||||
// Messages delivery proof is just proof of single storage key read => any error
|
||||
// is fatal.
|
||||
let storage_inbound_lane_data_key =
|
||||
bp_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane);
|
||||
let raw_inbound_lane_data = storage
|
||||
.read_value(storage_inbound_lane_data_key.0.as_ref())
|
||||
.map_err(|_| "Failed to read inbound lane state from storage proof")?
|
||||
.ok_or("Inbound lane state is missing from the messages proof")?;
|
||||
let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..])
|
||||
.map_err(|_| "Failed to decode inbound lane state from the proof")?;
|
||||
|
||||
Ok((lane, inbound_lane_data))
|
||||
},
|
||||
|storage| do_verify_messages_delivery_proof::<
|
||||
B,
|
||||
bp_runtime::HasherOf<
|
||||
<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain,
|
||||
>,
|
||||
>(lane, storage),
|
||||
)
|
||||
.map_err(<&'static str>::from)?
|
||||
}
|
||||
|
||||
/// Verify proof of This -> Bridged chain messages delivery.
|
||||
///
|
||||
/// This function is used when Bridged chain is using parachain finality. For Bridged
|
||||
/// chains with direct GRANDPA finality, please use the `verify_messages_delivery_proof`.
|
||||
///
|
||||
/// This function currently only supports parachains, which are using header type that
|
||||
/// implements `sp_runtime::traits::Header` trait.
|
||||
pub fn verify_messages_delivery_proof_from_parachain<
|
||||
B,
|
||||
BridgedHeader,
|
||||
ThisRuntime,
|
||||
ParachainsInstance: 'static,
|
||||
>(
|
||||
bridged_parachain: ParaId,
|
||||
proof: FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain<B>>>,
|
||||
) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str>
|
||||
where
|
||||
B: MessageBridge,
|
||||
B::BridgedChain: ChainWithMessages<Hash = ParaHash>,
|
||||
BridgedHeader: HeaderT<Hash = HashOf<BridgedChain<B>>>,
|
||||
ThisRuntime: pallet_bridge_parachains::Config<ParachainsInstance>,
|
||||
{
|
||||
let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } =
|
||||
proof;
|
||||
pallet_bridge_parachains::Pallet::<ThisRuntime, ParachainsInstance>::parse_finalized_storage_proof(
|
||||
bridged_parachain,
|
||||
bridged_header_hash,
|
||||
StorageProof::new(storage_proof),
|
||||
|para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()),
|
||||
|storage| do_verify_messages_delivery_proof::<B, ParaHasher>(lane, storage),
|
||||
)
|
||||
.map_err(<&'static str>::from)?
|
||||
}
|
||||
|
||||
/// The essense of This -> Bridged chain messages delivery proof verification.
|
||||
fn do_verify_messages_delivery_proof<B: MessageBridge, H: Hasher>(
|
||||
lane: LaneId,
|
||||
storage: bp_runtime::StorageProofChecker<H>,
|
||||
) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str> {
|
||||
// Messages delivery proof is just proof of single storage key read => any error
|
||||
// is fatal.
|
||||
let storage_inbound_lane_data_key = bp_messages::storage_keys::inbound_lane_data_key(
|
||||
B::BRIDGED_MESSAGES_PALLET_NAME,
|
||||
&lane,
|
||||
);
|
||||
let raw_inbound_lane_data = storage
|
||||
.read_value(storage_inbound_lane_data_key.0.as_ref())
|
||||
.map_err(|_| "Failed to read inbound lane state from storage proof")?
|
||||
.ok_or("Inbound lane state is missing from the messages proof")?;
|
||||
let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..])
|
||||
.map_err(|_| "Failed to decode inbound lane state from the proof")?;
|
||||
|
||||
Ok((lane, inbound_lane_data))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sub-module that is declaring types required for processing Bridged -> This chain messages.
|
||||
@@ -590,6 +641,9 @@ pub mod target {
|
||||
|
||||
/// Verify proof of Bridged -> This chain messages.
|
||||
///
|
||||
/// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged
|
||||
/// parachains, please use the `verify_messages_proof_from_parachain`.
|
||||
///
|
||||
/// The `messages_count` argument verification (sane limits) is supposed to be made
|
||||
/// outside of this function. This function only verifies that the proof declares exactly
|
||||
/// `messages_count` messages.
|
||||
@@ -624,6 +678,54 @@ pub mod target {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Verify proof of Bridged -> This chain messages.
|
||||
///
|
||||
/// This function is used when Bridged chain is using parachain finality. For Bridged
|
||||
/// chains with direct GRANDPA finality, please use the `verify_messages_proof`.
|
||||
///
|
||||
/// The `messages_count` argument verification (sane limits) is supposed to be made
|
||||
/// outside of this function. This function only verifies that the proof declares exactly
|
||||
/// `messages_count` messages.
|
||||
///
|
||||
/// This function currently only supports parachains, which are using header type that
|
||||
/// implements `sp_runtime::traits::Header` trait.
|
||||
pub fn verify_messages_proof_from_parachain<
|
||||
B,
|
||||
BridgedHeader,
|
||||
ThisRuntime,
|
||||
ParachainsInstance: 'static,
|
||||
>(
|
||||
bridged_parachain: ParaId,
|
||||
proof: FromBridgedChainMessagesProof<HashOf<BridgedChain<B>>>,
|
||||
messages_count: u32,
|
||||
) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, &'static str>
|
||||
where
|
||||
B: MessageBridge,
|
||||
B::BridgedChain: ChainWithMessages<Hash = ParaHash>,
|
||||
BridgedHeader: HeaderT<Hash = HashOf<BridgedChain<B>>>,
|
||||
ThisRuntime: pallet_bridge_parachains::Config<ParachainsInstance>,
|
||||
{
|
||||
verify_messages_proof_with_parser::<B, _, _>(
|
||||
proof,
|
||||
messages_count,
|
||||
|bridged_header_hash, bridged_storage_proof| {
|
||||
pallet_bridge_parachains::Pallet::<ThisRuntime, ParachainsInstance>::parse_finalized_storage_proof(
|
||||
bridged_parachain,
|
||||
bridged_header_hash,
|
||||
StorageProof::new(bridged_storage_proof),
|
||||
|para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()),
|
||||
|storage_adapter| storage_adapter,
|
||||
)
|
||||
.map(|storage| StorageProofCheckerAdapter::<_, B> {
|
||||
storage,
|
||||
_dummy: Default::default(),
|
||||
})
|
||||
.map_err(|err| MessageProofError::Custom(err.into()))
|
||||
},
|
||||
)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum MessageProofError {
|
||||
Empty,
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use bp_parachains::parachain_head_storage_key_at_source;
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::RuntimeDebug;
|
||||
use scale_info::TypeInfo;
|
||||
@@ -67,6 +67,12 @@ pub mod pallet {
|
||||
UnknownRelayChainBlock,
|
||||
/// Invalid storage proof has been passed.
|
||||
InvalidStorageProof,
|
||||
/// Given parachain head is unknown.
|
||||
UnknownParaHead,
|
||||
/// The storage proof doesn't contains storage root. So it is invalid for given header.
|
||||
StorageRootMismatch,
|
||||
/// Failed to extract state root from given parachain head.
|
||||
FailedToExtractStateRoot,
|
||||
}
|
||||
|
||||
#[pallet::config]
|
||||
@@ -190,6 +196,38 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Get best finalized header of the given parachain.
|
||||
pub fn best_parachain_head(parachain: ParaId) -> Option<ParaHead> {
|
||||
let best_para_head_hash = BestParaHeads::<T, I>::get(parachain)?.head_hash;
|
||||
ImportedParaHeads::<T, I>::get(parachain, best_para_head_hash)
|
||||
}
|
||||
|
||||
/// Get parachain head with given hash.
|
||||
pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option<ParaHead> {
|
||||
ImportedParaHeads::<T, I>::get(parachain, hash)
|
||||
}
|
||||
|
||||
/// Verify that the passed storage proof is valid, given it is crafted using
|
||||
/// known finalized header. If the proof is valid, then the `parse` callback
|
||||
/// is called and the function returns its result.
|
||||
pub fn parse_finalized_storage_proof<R>(
|
||||
parachain: ParaId,
|
||||
hash: ParaHash,
|
||||
storage_proof: sp_trie::StorageProof,
|
||||
decode_state_root: impl FnOnce(ParaHead) -> Option<ParaHash>,
|
||||
parse: impl FnOnce(bp_runtime::StorageProofChecker<ParaHasher>) -> R,
|
||||
) -> Result<R, sp_runtime::DispatchError> {
|
||||
let para_head =
|
||||
Self::parachain_head(parachain, hash).ok_or(Error::<T, I>::UnknownParaHead)?;
|
||||
let state_root =
|
||||
decode_state_root(para_head).ok_or(Error::<T, I>::FailedToExtractStateRoot)?;
|
||||
let storage_proof_checker =
|
||||
bp_runtime::StorageProofChecker::new(state_root, storage_proof)
|
||||
.map_err(|_| Error::<T, I>::StorageRootMismatch)?;
|
||||
|
||||
Ok(parse(storage_proof_checker))
|
||||
}
|
||||
|
||||
/// Read parachain head from storage proof.
|
||||
fn read_parachain_head(
|
||||
storage: &bp_runtime::StorageProofChecker<RelayBlockHasher>,
|
||||
@@ -329,7 +367,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn prepare_parachain_heads_proof(
|
||||
heads: Vec<(ParaId, ParaHead)>,
|
||||
heads: Vec<(u32, ParaHead)>,
|
||||
) -> (RelayBlockHash, ParaHeadsProof) {
|
||||
let mut root = Default::default();
|
||||
let mut mdb = MemoryDB::default();
|
||||
@@ -337,7 +375,7 @@ mod tests {
|
||||
let mut trie = TrieDBMutV1::<RelayBlockHasher>::new(&mut mdb, &mut root);
|
||||
for (parachain, head) in heads {
|
||||
let storage_key =
|
||||
parachain_head_storage_key_at_source(PARAS_PALLET_NAME, parachain);
|
||||
parachain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(parachain));
|
||||
trie.insert(&storage_key.0, &head.encode())
|
||||
.map_err(|_| "TrieMut::insert has failed")
|
||||
.expect("TrieMut::insert should not fail in tests");
|
||||
@@ -385,10 +423,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn imports_initial_parachain_heads() {
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![
|
||||
(ParaId(1), head_data(1, 0)),
|
||||
(ParaId(3), head_data(3, 10)),
|
||||
]);
|
||||
let (state_root, proof) =
|
||||
prepare_parachain_heads_proof(vec![(1, head_data(1, 0)), (3, head_data(3, 10))]);
|
||||
run_test(|| {
|
||||
initialize(state_root);
|
||||
|
||||
@@ -429,10 +465,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn imports_parachain_heads_is_able_to_progress() {
|
||||
let (state_root_5, proof_5) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]);
|
||||
let (state_root_10, proof_10) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]);
|
||||
let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
|
||||
let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]);
|
||||
run_test(|| {
|
||||
// start with relay block #0 and import head#5 of parachain#1
|
||||
initialize(state_root_5);
|
||||
@@ -478,7 +512,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn does_nothing_when_already_imported_this_head_at_previous_relay_header() {
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 0))]);
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]);
|
||||
run_test(|| {
|
||||
// import head#0 of parachain#1 at relay block#0
|
||||
initialize(state_root);
|
||||
@@ -495,10 +529,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn does_nothing_when_already_imported_head_at_better_relay_header() {
|
||||
let (state_root_5, proof_5) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]);
|
||||
let (state_root_10, proof_10) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]);
|
||||
let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
|
||||
let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]);
|
||||
run_test(|| {
|
||||
// start with relay block #0
|
||||
initialize(state_root_5);
|
||||
@@ -536,8 +568,7 @@ mod tests {
|
||||
|
||||
// import exactly `HeadsToKeep` headers
|
||||
for i in 0..heads_to_keep {
|
||||
let (state_root, proof) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, i))]);
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, i))]);
|
||||
if i == 0 {
|
||||
initialize(state_root);
|
||||
} else {
|
||||
@@ -554,7 +585,7 @@ mod tests {
|
||||
|
||||
// import next relay chain header and next parachain head
|
||||
let (state_root, proof) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, heads_to_keep))]);
|
||||
prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]);
|
||||
proceed(heads_to_keep, state_root);
|
||||
assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof));
|
||||
|
||||
@@ -571,7 +602,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn fails_on_unknown_relay_chain_block() {
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]);
|
||||
let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
|
||||
run_test(|| {
|
||||
// start with relay block #0
|
||||
initialize(state_root);
|
||||
@@ -586,8 +617,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn fails_on_invalid_storage_proof() {
|
||||
let (_state_root, proof) =
|
||||
prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]);
|
||||
let (_state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
|
||||
run_test(|| {
|
||||
// start with relay block #0
|
||||
initialize(Default::default());
|
||||
|
||||
@@ -241,6 +241,21 @@ pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount<AccountId>) -
|
||||
AccountIdConverter::convert(encoded_id)
|
||||
}
|
||||
|
||||
/// We use this to get the account on Millau (target) which is derived from RialtoParachain's
|
||||
/// (source) account. We do this so we can fund the derived account on Millau at Genesis to it can
|
||||
/// pay transaction fees.
|
||||
///
|
||||
/// The reason we can use the same `AccountId` type for both chains is because they share the same
|
||||
/// development seed phrase.
|
||||
///
|
||||
/// Note that this should only be used for testing.
|
||||
pub fn derive_account_from_rialto_parachain_id(
|
||||
id: bp_runtime::SourceAccount<AccountId>,
|
||||
) -> AccountId {
|
||||
let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_PARACHAIN_CHAIN_ID, id);
|
||||
AccountIdConverter::convert(encoded_id)
|
||||
}
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub BlockLength: limits::BlockLength =
|
||||
limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
|
||||
|
||||
@@ -18,19 +18,32 @@
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bp_messages::{LaneId, MessageDetails, MessageNonce};
|
||||
use bp_runtime::Chain;
|
||||
use frame_support::{
|
||||
weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight},
|
||||
RuntimeDebug,
|
||||
Parameter, RuntimeDebug,
|
||||
};
|
||||
use frame_system::limits;
|
||||
use sp_core::Hasher as HasherT;
|
||||
use sp_runtime::{
|
||||
traits::{BlakeTwo256, IdentifyAccount, Verify},
|
||||
MultiSignature, MultiSigner, Perbill,
|
||||
traits::{BlakeTwo256, Convert, IdentifyAccount, Verify},
|
||||
FixedU128, MultiSignature, MultiSigner, Perbill,
|
||||
};
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
/// Maximal weight of single Rialto parachain block.
|
||||
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
|
||||
/// RialtoParachain chain. This mostly depends on number of entries (and their density) in the
|
||||
/// storage trie. Some reserve is reserved to account future chain growth.
|
||||
pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024;
|
||||
|
||||
/// Can be computed by subtracting encoded call size from raw transaction size.
|
||||
pub const TX_EXTRA_BYTES: u32 = 104;
|
||||
|
||||
/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id.
|
||||
pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32;
|
||||
|
||||
/// Maximal weight of single RialtoParachain block.
|
||||
///
|
||||
/// This represents two seconds of compute assuming a target block time of six seconds.
|
||||
pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND;
|
||||
@@ -42,6 +55,44 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
|
||||
/// Represents the portion of a block that will be used by Normal extrinsics.
|
||||
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
|
||||
|
||||
/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction.
|
||||
pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024;
|
||||
|
||||
/// Maximal number of unconfirmed messages in Rialto confirmation transaction.
|
||||
pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024;
|
||||
|
||||
/// Weight of single regular message delivery transaction on RialtoParachain chain.
|
||||
///
|
||||
/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call
|
||||
/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH`
|
||||
/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be
|
||||
/// rounded up to account possible future runtime upgrades.
|
||||
pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000;
|
||||
|
||||
/// Increase of delivery transaction weight on RialtoParachain chain with every additional message
|
||||
/// byte.
|
||||
///
|
||||
/// This value is a result of
|
||||
/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then
|
||||
/// must be rounded up to account possible future runtime upgrades.
|
||||
pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000;
|
||||
|
||||
/// Maximal weight of single message delivery confirmation transaction on RialtoParachain chain.
|
||||
///
|
||||
/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof`
|
||||
/// weight formula computation for the case when single message is confirmed. The result then must
|
||||
/// be rounded up to account possible future runtime upgrades.
|
||||
pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000;
|
||||
|
||||
/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain.
|
||||
///
|
||||
/// This value corresponds to the result of
|
||||
/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your
|
||||
/// chain. Don't put too much reserve there, because it is used to **decrease**
|
||||
/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery
|
||||
/// transactions cheaper.
|
||||
pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000;
|
||||
|
||||
/// Block number type used in Rialto.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
@@ -103,6 +154,15 @@ impl Chain for RialtoParachain {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a 256-bit hash into an AccountId.
|
||||
pub struct AccountIdConverter;
|
||||
|
||||
impl Convert<sp_core::H256, AccountId> for AccountIdConverter {
|
||||
fn convert(hash: sp_core::H256) -> AccountId {
|
||||
hash.to_fixed_bytes().into()
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub BlockLength: limits::BlockLength =
|
||||
limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
|
||||
@@ -122,3 +182,93 @@ frame_support::parameter_types! {
|
||||
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
|
||||
.build_or_panic();
|
||||
}
|
||||
|
||||
/// Name of the With-Rialto-Parachain messages pallet instance that is deployed at bridged chains.
|
||||
pub const WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeRialtoParachainMessages";
|
||||
|
||||
/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto parachain
|
||||
/// runtime.
|
||||
pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate";
|
||||
|
||||
/// Name of the `RialtoParachainFinalityApi::best_finalized` runtime method.
|
||||
pub const BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD: &str =
|
||||
"RialtoParachainFinalityApi_best_finalized";
|
||||
|
||||
/// Name of the `ToRialtoParachainOutboundLaneApi::estimate_message_delivery_and_dispatch_fee`
|
||||
/// runtime method.
|
||||
pub const TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD: &str =
|
||||
"ToRialtoParachainOutboundLaneApi_estimate_message_delivery_and_dispatch_fee";
|
||||
/// Name of the `ToRialtoParachainOutboundLaneApi::message_details` runtime method.
|
||||
pub const TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str =
|
||||
"ToRialtoParachainOutboundLaneApi_message_details";
|
||||
|
||||
// We use this to get the account on RialtoParachain (target) which is derived from Millau's
|
||||
// (source) account. We do this so we can fund the derived account on RialtoParachain at Genesis to
|
||||
// it can pay transaction fees.
|
||||
//
|
||||
// The reason we can use the same `AccountId` type for both chains is because they share the same
|
||||
// development seed phrase.
|
||||
//
|
||||
// Note that this should only be used for testing.
|
||||
pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId {
|
||||
let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_CHAIN_ID, id);
|
||||
AccountIdConverter::convert(encoded_id)
|
||||
}
|
||||
|
||||
sp_api::decl_runtime_apis! {
|
||||
/// API for querying information about the finalized RialtoParachain headers.
|
||||
///
|
||||
/// This API is implemented by runtimes that are bridging with the RialtoParachain chain, not the
|
||||
/// RialtoParachain runtime itself.
|
||||
pub trait RialtoParachainFinalityApi {
|
||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||
fn best_finalized() -> (BlockNumber, Hash);
|
||||
}
|
||||
|
||||
/// Outbound message lane API for messages that are sent to RialtoParachain chain.
|
||||
///
|
||||
/// This API is implemented by runtimes that are sending messages to RialtoParachain chain, not the
|
||||
/// RialtoParachain runtime itself.
|
||||
pub trait ToRialtoParachainOutboundLaneApi<OutboundMessageFee: Parameter, OutboundPayload: Parameter> {
|
||||
/// Estimate message delivery and dispatch fee that needs to be paid by the sender on
|
||||
/// this chain.
|
||||
///
|
||||
/// Returns `None` if message is too expensive to be sent to RialtoParachain from this chain.
|
||||
///
|
||||
/// Please keep in mind that this method returns the lowest message fee required for message
|
||||
/// to be accepted to the lane. It may be good idea to pay a bit over this price to account
|
||||
/// future exchange rate changes and guarantee that relayer would deliver your message
|
||||
/// to the target chain.
|
||||
fn estimate_message_delivery_and_dispatch_fee(
|
||||
lane_id: LaneId,
|
||||
payload: OutboundPayload,
|
||||
rialto_parachain_to_this_conversion_rate: Option<FixedU128>,
|
||||
) -> Option<OutboundMessageFee>;
|
||||
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
|
||||
/// messages in given inclusive range.
|
||||
///
|
||||
/// If some (or all) messages are missing from the storage, they'll also will
|
||||
/// be missing from the resulting vector. The vector is ordered by the nonce.
|
||||
fn message_details(
|
||||
lane: LaneId,
|
||||
begin: MessageNonce,
|
||||
end: MessageNonce,
|
||||
) -> Vec<MessageDetails<OutboundMessageFee>>;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_runtime::codec::Encode;
|
||||
|
||||
#[test]
|
||||
fn maximal_account_size_does_not_overflow_constant() {
|
||||
assert!(
|
||||
MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(),
|
||||
"Actual maximal size of encoded AccountId ({}) overflows expected ({})",
|
||||
AccountId::from([0u8; 32]).encode().len(),
|
||||
MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ sp_api::decl_runtime_apis! {
|
||||
/// API for querying information about the finalized Rialto headers.
|
||||
///
|
||||
/// This API is implemented by runtimes that are bridging with the Rialto chain, not the
|
||||
/// Millau runtime itself.
|
||||
/// Rialto runtime itself.
|
||||
pub trait RialtoFinalityApi {
|
||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||
fn best_finalized() -> (BlockNumber, Hash);
|
||||
|
||||
@@ -55,6 +55,12 @@ use parity_util_mem::MallocSizeOf;
|
||||
)]
|
||||
pub struct ParaId(pub u32);
|
||||
|
||||
impl From<u32> for ParaId {
|
||||
fn from(id: u32) -> Self {
|
||||
ParaId(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parachain head.
|
||||
///
|
||||
/// This is an equivalent of the `polkadot_parachain::HeadData`.
|
||||
@@ -78,5 +84,8 @@ impl ParaHead {
|
||||
/// Parachain head hash.
|
||||
pub type ParaHash = crate::Hash;
|
||||
|
||||
/// Parachain head hasher.
|
||||
pub type ParaHasher = crate::Hasher;
|
||||
|
||||
/// Raw storage proof of parachain heads, stored in polkadot-like chain runtime.
|
||||
pub type ParaHeadsProof = Vec<Vec<u8>>;
|
||||
|
||||
@@ -45,6 +45,9 @@ pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0];
|
||||
/// Bridge-with-Rialto instance id.
|
||||
pub const RIALTO_CHAIN_ID: ChainId = *b"rlto";
|
||||
|
||||
/// Bridge-with-RialtoParachain instance id.
|
||||
pub const RIALTO_PARACHAIN_CHAIN_ID: ChainId = *b"rlpa";
|
||||
|
||||
/// Bridge-with-Millau instance id.
|
||||
pub const MILLAU_CHAIN_ID: ChainId = *b"mlau";
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ bp-header-chain = { path = "../../primitives/header-chain" }
|
||||
bp-kusama = { path = "../../primitives/chain-kusama" }
|
||||
bp-messages = { path = "../../primitives/messages" }
|
||||
bp-millau = { path = "../../primitives/chain-millau" }
|
||||
bp-parachains = { path = "../../primitives/parachains" }
|
||||
bp-polkadot = { path = "../../primitives/chain-polkadot" }
|
||||
bp-polkadot-core = { path = "../../primitives/polkadot-core" }
|
||||
bp-rialto = { path = "../../primitives/chain-rialto" }
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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/>.
|
||||
|
||||
//! Millau-to-RialtoParachain headers sync entrypoint.
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! Millau-to-RialtoParachain headers sync entrypoint.
|
||||
|
||||
use substrate_relay_helper::finality::{
|
||||
engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder,
|
||||
SubstrateFinalitySyncPipeline,
|
||||
};
|
||||
|
||||
/// Description of Millau -> Rialto finalized headers bridge.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MillauFinalityToRialtoParachain;
|
||||
|
||||
impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain {
|
||||
type SourceChain = relay_millau_client::Millau;
|
||||
type TargetChain = relay_rialto_parachain_client::RialtoParachain;
|
||||
|
||||
type FinalityEngine = GrandpaFinalityEngine<Self::SourceChain>;
|
||||
type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder<
|
||||
Self,
|
||||
rialto_parachain_runtime::Runtime,
|
||||
rialto_parachain_runtime::MillauGrandpaInstance,
|
||||
>;
|
||||
type TransactionSignScheme = relay_rialto_parachain_client::RialtoParachain;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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/>.
|
||||
|
||||
//! Millau-to-RialtoParachain messages sync entrypoint.
|
||||
|
||||
use messages_relay::relay_strategy::MixStrategy;
|
||||
use relay_millau_client::Millau;
|
||||
use relay_rialto_parachain_client::RialtoParachain;
|
||||
use substrate_relay_helper::messages_lane::{
|
||||
DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder,
|
||||
SubstrateMessageLane,
|
||||
};
|
||||
|
||||
/// Description of Millau -> RialtoParachain messages bridge.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MillauMessagesToRialtoParachain;
|
||||
|
||||
impl SubstrateMessageLane for MillauMessagesToRialtoParachain {
|
||||
const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
|
||||
Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME);
|
||||
const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
|
||||
Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME);
|
||||
|
||||
const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None;
|
||||
const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None;
|
||||
const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None;
|
||||
const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None;
|
||||
|
||||
type SourceChain = Millau;
|
||||
type TargetChain = RialtoParachain;
|
||||
|
||||
type SourceTransactionSignScheme = Millau;
|
||||
type TargetTransactionSignScheme = RialtoParachain;
|
||||
|
||||
type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder<
|
||||
Self,
|
||||
rialto_parachain_runtime::Runtime,
|
||||
rialto_parachain_runtime::WithMillauMessagesInstance,
|
||||
>;
|
||||
type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder<
|
||||
Self,
|
||||
millau_runtime::Runtime,
|
||||
millau_runtime::WithRialtoParachainMessagesInstance,
|
||||
>;
|
||||
|
||||
type TargetToSourceChainConversionRateUpdateBuilder = ();
|
||||
|
||||
type RelayStrategy = MixStrategy;
|
||||
}
|
||||
@@ -19,11 +19,14 @@
|
||||
pub mod kusama_headers_to_polkadot;
|
||||
pub mod kusama_messages_to_polkadot;
|
||||
pub mod millau_headers_to_rialto;
|
||||
pub mod millau_headers_to_rialto_parachain;
|
||||
pub mod millau_messages_to_rialto;
|
||||
pub mod millau_messages_to_rialto_parachain;
|
||||
pub mod polkadot_headers_to_kusama;
|
||||
pub mod polkadot_messages_to_kusama;
|
||||
pub mod rialto_headers_to_millau;
|
||||
pub mod rialto_messages_to_millau;
|
||||
pub mod rialto_parachain_messages_to_millau;
|
||||
pub mod rialto_parachains_to_millau;
|
||||
pub mod rococo_headers_to_wococo;
|
||||
pub mod rococo_messages_to_wococo;
|
||||
|
||||
@@ -16,10 +16,42 @@
|
||||
|
||||
//! Rialto parachain specification for CLI.
|
||||
|
||||
use crate::cli::CliChain;
|
||||
use crate::cli::{
|
||||
bridge,
|
||||
encode_message::{CliEncodeMessage, RawMessage},
|
||||
CliChain,
|
||||
};
|
||||
use bp_messages::LaneId;
|
||||
use bp_runtime::EncodedOrDecodedCall;
|
||||
use relay_rialto_parachain_client::RialtoParachain;
|
||||
use relay_substrate_client::BalanceOf;
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
impl CliEncodeMessage for RialtoParachain {
|
||||
fn encode_send_message_call(
|
||||
lane: LaneId,
|
||||
payload: RawMessage,
|
||||
fee: BalanceOf<Self>,
|
||||
bridge_instance_index: u8,
|
||||
) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> {
|
||||
Ok(match bridge_instance_index {
|
||||
bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX =>
|
||||
rialto_parachain_runtime::Call::BridgeMillauMessages(
|
||||
rialto_parachain_runtime::MessagesCall::send_message {
|
||||
lane_id: lane,
|
||||
payload,
|
||||
delivery_and_dispatch_fee: fee,
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
_ => anyhow::bail!(
|
||||
"Unsupported target bridge pallet with instance index: {}",
|
||||
bridge_instance_index
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CliChain for RialtoParachain {
|
||||
const RUNTIME_VERSION: RuntimeVersion = rialto_parachain_runtime::VERSION;
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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/>.
|
||||
|
||||
//! RialtoParachain-to-Millau messages sync entrypoint.
|
||||
|
||||
use messages_relay::relay_strategy::MixStrategy;
|
||||
use relay_millau_client::Millau;
|
||||
use relay_rialto_parachain_client::RialtoParachain;
|
||||
use substrate_relay_helper::messages_lane::{
|
||||
DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder,
|
||||
SubstrateMessageLane,
|
||||
};
|
||||
|
||||
/// Description of RialtoParachain -> Millau messages bridge.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RialtoParachainMessagesToMillau;
|
||||
|
||||
impl SubstrateMessageLane for RialtoParachainMessagesToMillau {
|
||||
const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
|
||||
Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME);
|
||||
const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
|
||||
Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME);
|
||||
|
||||
const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None;
|
||||
const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None;
|
||||
const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None;
|
||||
const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None;
|
||||
|
||||
type SourceChain = RialtoParachain;
|
||||
type TargetChain = Millau;
|
||||
|
||||
type SourceTransactionSignScheme = RialtoParachain;
|
||||
type TargetTransactionSignScheme = Millau;
|
||||
|
||||
type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder<
|
||||
Self,
|
||||
millau_runtime::Runtime,
|
||||
millau_runtime::WithRialtoParachainMessagesInstance,
|
||||
>;
|
||||
type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder<
|
||||
Self,
|
||||
rialto_parachain_runtime::Runtime,
|
||||
rialto_parachain_runtime::WithMillauMessagesInstance,
|
||||
>;
|
||||
|
||||
type TargetToSourceChainConversionRateUpdateBuilder = ();
|
||||
|
||||
type RelayStrategy = MixStrategy;
|
||||
}
|
||||
@@ -23,17 +23,17 @@ use substrate_relay_helper::parachains_target::DirectSubmitParachainHeadsCallBui
|
||||
|
||||
/// Rialto-to-Millau parachains sync description.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RialtoToMillauParachains;
|
||||
pub struct RialtoParachainsToMillau;
|
||||
|
||||
impl ParachainsPipeline for RialtoToMillauParachains {
|
||||
impl ParachainsPipeline for RialtoParachainsToMillau {
|
||||
type SourceChain = Rialto;
|
||||
type TargetChain = Millau;
|
||||
}
|
||||
|
||||
/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline.
|
||||
pub type RialtoToMillauParachainsSubmitParachainHeadsCallBuilder =
|
||||
pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder =
|
||||
DirectSubmitParachainHeadsCallBuilder<
|
||||
RialtoToMillauParachains,
|
||||
RialtoParachainsToMillau,
|
||||
millau_runtime::Runtime,
|
||||
millau_runtime::WitRialtoParachainsInstance,
|
||||
>;
|
||||
|
||||
@@ -26,6 +26,8 @@ pub enum FullBridge {
|
||||
WococoToRococo,
|
||||
KusamaToPolkadot,
|
||||
PolkadotToKusama,
|
||||
MillauToRialtoParachain,
|
||||
RialtoParachainToMillau,
|
||||
}
|
||||
|
||||
impl FullBridge {
|
||||
@@ -38,6 +40,8 @@ impl FullBridge {
|
||||
Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX,
|
||||
Self::KusamaToPolkadot => KUSAMA_TO_POLKADOT_INDEX,
|
||||
Self::PolkadotToKusama => POLKADOT_TO_KUSAMA_INDEX,
|
||||
Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX,
|
||||
Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +52,8 @@ pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0;
|
||||
pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0;
|
||||
pub const KUSAMA_TO_POLKADOT_INDEX: u8 = 0;
|
||||
pub const POLKADOT_TO_KUSAMA_INDEX: u8 = 0;
|
||||
pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1;
|
||||
pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0;
|
||||
|
||||
/// The macro allows executing bridge-specific code without going fully generic.
|
||||
///
|
||||
@@ -171,6 +177,44 @@ macro_rules! select_full_bridge {
|
||||
|
||||
$generic
|
||||
},
|
||||
FullBridge::MillauToRialtoParachain => {
|
||||
type Source = relay_millau_client::Millau;
|
||||
#[allow(dead_code)]
|
||||
type Target = relay_rialto_parachain_client::RialtoParachain;
|
||||
|
||||
// Derive-account
|
||||
#[allow(unused_imports)]
|
||||
use bp_rialto_parachain::derive_account_from_millau_id as derive_account;
|
||||
|
||||
// Relay-messages
|
||||
#[allow(unused_imports)]
|
||||
use crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane;
|
||||
|
||||
// Send-message / Estimate-fee
|
||||
#[allow(unused_imports)]
|
||||
use bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
|
||||
|
||||
$generic
|
||||
}
|
||||
FullBridge::RialtoParachainToMillau => {
|
||||
type Source = relay_rialto_parachain_client::RialtoParachain;
|
||||
#[allow(dead_code)]
|
||||
type Target = relay_millau_client::Millau;
|
||||
|
||||
// Derive-account
|
||||
#[allow(unused_imports)]
|
||||
use bp_millau::derive_account_from_rialto_parachain_id as derive_account;
|
||||
|
||||
// Relay-messages
|
||||
#[allow(unused_imports)]
|
||||
use crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane;
|
||||
|
||||
// Send-message / Estimate-fee
|
||||
#[allow(unused_imports)]
|
||||
use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
|
||||
|
||||
$generic
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ pub enum InitBridgeName {
|
||||
WococoToRococo,
|
||||
KusamaToPolkadot,
|
||||
PolkadotToKusama,
|
||||
MillauToRialtoParachain,
|
||||
}
|
||||
|
||||
macro_rules! select_bridge {
|
||||
@@ -181,6 +182,28 @@ macro_rules! select_bridge {
|
||||
)
|
||||
}
|
||||
|
||||
$generic
|
||||
},
|
||||
InitBridgeName::MillauToRialtoParachain => {
|
||||
type Source = relay_millau_client::Millau;
|
||||
type Target = relay_rialto_parachain_client::RialtoParachain;
|
||||
type Engine = GrandpaFinalityEngine<Source>;
|
||||
|
||||
fn encode_init_bridge(
|
||||
init_data: InitializationData<<Source as ChainBase>::Header>,
|
||||
) -> <Target as Chain>::Call {
|
||||
let initialize_call = rialto_parachain_runtime::BridgeGrandpaCall::<
|
||||
rialto_parachain_runtime::Runtime,
|
||||
rialto_parachain_runtime::MillauGrandpaInstance,
|
||||
>::initialize {
|
||||
init_data,
|
||||
};
|
||||
rialto_parachain_runtime::SudoCall::sudo {
|
||||
call: Box::new(initialize_call.into()),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
$generic
|
||||
},
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ pub enum RelayHeadersBridge {
|
||||
WococoToRococo,
|
||||
KusamaToPolkadot,
|
||||
PolkadotToKusama,
|
||||
MillauToRialtoParachain,
|
||||
}
|
||||
|
||||
macro_rules! select_bridge {
|
||||
@@ -109,6 +110,14 @@ macro_rules! select_bridge {
|
||||
|
||||
$generic
|
||||
},
|
||||
RelayHeadersBridge::MillauToRialtoParachain => {
|
||||
type Source = relay_millau_client::Millau;
|
||||
type Target = relay_rialto_parachain_client::RialtoParachain;
|
||||
type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain;
|
||||
|
||||
$generic
|
||||
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -480,7 +480,6 @@ impl RelayHeadersAndMessages {
|
||||
right_to_left_transaction_params,
|
||||
params.shared.only_mandatory_headers,
|
||||
);
|
||||
|
||||
// Need 2x capacity since we consider both directions for each lane
|
||||
let mut message_relays = Vec::with_capacity(lanes.len() * 2);
|
||||
for lane in lanes {
|
||||
|
||||
@@ -55,8 +55,8 @@ macro_rules! select_bridge {
|
||||
match $bridge {
|
||||
RelayParachainsBridge::RialtoToMillau => {
|
||||
use crate::chains::rialto_parachains_to_millau::{
|
||||
RialtoToMillauParachains as Pipeline,
|
||||
RialtoToMillauParachainsSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder,
|
||||
RialtoParachainsToMillau as Pipeline,
|
||||
RialtoParachainsToMillauSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder,
|
||||
};
|
||||
|
||||
use bp_millau::BRIDGE_PARAS_PALLET_NAME as BRIDGE_PARAS_PALLET_NAME_AT_TARGET;
|
||||
|
||||
@@ -6,12 +6,14 @@ edition = "2021"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "3.0.0" }
|
||||
relay-substrate-client = { path = "../client-substrate" }
|
||||
relay-utils = { path = "../utils" }
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-rialto = { path = "../../primitives/chain-rialto" }
|
||||
bp-messages = { path = "../../primitives/messages" }
|
||||
bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" }
|
||||
rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" }
|
||||
|
||||
# Substrate Dependencies
|
||||
@@ -19,3 +21,5 @@ rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -16,8 +16,15 @@
|
||||
|
||||
//! Types used to connect to the Rialto-Substrate chain.
|
||||
|
||||
use bp_messages::MessageNonce;
|
||||
use codec::Encode;
|
||||
use frame_support::weights::Weight;
|
||||
use relay_substrate_client::{Chain, ChainBase};
|
||||
use relay_substrate_client::{
|
||||
Chain, ChainBase, ChainWithBalances, ChainWithMessages, Error as SubstrateError, SignParam,
|
||||
TransactionSignScheme, UnsignedTransaction,
|
||||
};
|
||||
use sp_core::{storage::StorageKey, Pair};
|
||||
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Rialto header id.
|
||||
@@ -40,11 +47,11 @@ impl ChainBase for RialtoParachain {
|
||||
type Signature = rialto_parachain_runtime::Signature;
|
||||
|
||||
fn max_extrinsic_size() -> u32 {
|
||||
bp_rialto::Rialto::max_extrinsic_size()
|
||||
bp_rialto_parachain::RialtoParachain::max_extrinsic_size()
|
||||
}
|
||||
|
||||
fn max_extrinsic_weight() -> Weight {
|
||||
bp_rialto::Rialto::max_extrinsic_weight()
|
||||
bp_rialto_parachain::RialtoParachain::max_extrinsic_weight()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +59,111 @@ impl Chain for RialtoParachain {
|
||||
const NAME: &'static str = "RialtoParachain";
|
||||
const TOKEN_ID: Option<&'static str> = None;
|
||||
// should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199
|
||||
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "<UNIMPLEMENTED>";
|
||||
// should be removed in https://github.com/paritytech/parity-bridges-common/issues/1246
|
||||
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||
bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD;
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 =
|
||||
bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type SignedBlock = rialto_parachain_runtime::SignedBlock;
|
||||
type Call = rialto_parachain_runtime::Call;
|
||||
type WeightToFee = bp_rialto::WeightToFee;
|
||||
type WeightToFee = bp_rialto_parachain::WeightToFee;
|
||||
}
|
||||
|
||||
impl ChainWithBalances for RialtoParachain {
|
||||
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
|
||||
use frame_support::storage::generator::StorageMap;
|
||||
StorageKey(
|
||||
frame_system::Account::<rialto_parachain_runtime::Runtime>::storage_map_final_key(
|
||||
account_id,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ChainWithMessages for RialtoParachain {
|
||||
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
|
||||
bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME;
|
||||
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
|
||||
bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD;
|
||||
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
|
||||
bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
|
||||
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
|
||||
bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
|
||||
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
|
||||
bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl TransactionSignScheme for RialtoParachain {
|
||||
type Chain = RialtoParachain;
|
||||
type AccountKeyPair = sp_core::sr25519::Pair;
|
||||
type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic;
|
||||
|
||||
fn sign_transaction(param: SignParam<Self>) -> Result<Self::SignedTransaction, SubstrateError> {
|
||||
let raw_payload = SignedPayload::from_raw(
|
||||
param.unsigned.call,
|
||||
(
|
||||
frame_system::CheckNonZeroSender::<rialto_parachain_runtime::Runtime>::new(),
|
||||
frame_system::CheckSpecVersion::<rialto_parachain_runtime::Runtime>::new(),
|
||||
frame_system::CheckTxVersion::<rialto_parachain_runtime::Runtime>::new(),
|
||||
frame_system::CheckGenesis::<rialto_parachain_runtime::Runtime>::new(),
|
||||
frame_system::CheckEra::<rialto_parachain_runtime::Runtime>::from(
|
||||
param.era.frame_era(),
|
||||
),
|
||||
frame_system::CheckNonce::<rialto_parachain_runtime::Runtime>::from(
|
||||
param.unsigned.nonce,
|
||||
),
|
||||
frame_system::CheckWeight::<rialto_parachain_runtime::Runtime>::new(),
|
||||
pallet_transaction_payment::ChargeTransactionPayment::<
|
||||
rialto_parachain_runtime::Runtime,
|
||||
>::from(param.unsigned.tip),
|
||||
),
|
||||
(
|
||||
(),
|
||||
param.spec_version,
|
||||
param.transaction_version,
|
||||
param.genesis_hash,
|
||||
param.era.signed_payload(param.genesis_hash),
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
),
|
||||
);
|
||||
let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
|
||||
let signer: sp_runtime::MultiSigner = param.signer.public().into();
|
||||
let (call, extra, _) = raw_payload.deconstruct();
|
||||
|
||||
Ok(rialto_parachain_runtime::UncheckedExtrinsic::new_signed(
|
||||
call.into_decoded()?,
|
||||
signer.into_account().into(),
|
||||
signature.into(),
|
||||
extra,
|
||||
))
|
||||
}
|
||||
|
||||
fn is_signed(tx: &Self::SignedTransaction) -> bool {
|
||||
tx.signature.is_some()
|
||||
}
|
||||
|
||||
fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool {
|
||||
tx.signature
|
||||
.as_ref()
|
||||
.map(|(address, _, _)| {
|
||||
*address == rialto_parachain_runtime::Address::Id(signer.public().into())
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn parse_transaction(_tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self::Chain>> {
|
||||
unimplemented!("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
/// RialtoParachain signing params.
|
||||
pub type SigningParams = sp_core::sr25519::Pair;
|
||||
|
||||
/// RialtoParachain header type used in headers sync.
|
||||
pub type SyncHeader = relay_substrate_client::SyncHeader<rialto_parachain_runtime::Header>;
|
||||
|
||||
@@ -298,6 +298,20 @@ fn select_parachains_to_update<P: ParachainsPipeline>(
|
||||
where
|
||||
P::SourceChain: Chain<BlockNumber = RelayBlockNumber>,
|
||||
{
|
||||
log::trace!(
|
||||
target: "bridge",
|
||||
"Selecting {} parachains to update at {} (relay block: {:?}):\n\t\
|
||||
At {}: {:?}\n\t\
|
||||
At {}: {:?}",
|
||||
P::SourceChain::NAME,
|
||||
P::TargetChain::NAME,
|
||||
best_finalized_relay_block,
|
||||
P::SourceChain::NAME,
|
||||
heads_at_source,
|
||||
P::TargetChain::NAME,
|
||||
heads_at_target,
|
||||
);
|
||||
|
||||
heads_at_source
|
||||
.into_iter()
|
||||
.zip(heads_at_target.into_iter())
|
||||
|
||||
Reference in New Issue
Block a user