messages bridge between RialtoParachain and Millau (#1218)

This commit is contained in:
Svyatoslav Nikolsky
2022-05-20 12:03:45 +03:00
committed by Bastian Köcher
parent 03c2f06a27
commit 5f2f61ced5
33 changed files with 1658 additions and 75 deletions
+9 -3
View File
@@ -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(),
}
}
+4
View File
@@ -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",
+98 -3
View File
@@ -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",
+125 -10
View File
@@ -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),
}
}
}
+1 -1
View File
@@ -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.
+4
View File
@@ -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",
+117 -15
View File
@@ -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 &para_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 &para_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,