Skip to content
This repository has been archived by the owner on Feb 29, 2024. It is now read-only.

Commit

Permalink
Sync missing changes from different branches (#191)
Browse files Browse the repository at this point in the history
  • Loading branch information
aurexav authored and jiguantong committed Sep 29, 2022
1 parent 6b02d31 commit fea209c
Show file tree
Hide file tree
Showing 10 changed files with 355 additions and 152 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 15 additions & 13 deletions bin/runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,33 @@ scale-info = { version = "2.0.1", default-features = false, features = ["derive"

bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false }
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-dispatch = { path = "../../modules/dispatch", default-features = false }
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
pallet-fee-market = { path = "../../modules/fee-market", default-features = false }
pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false }

# Substrate dependencies

frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }

[features]
default = ["std"]
std = [
"bp-message-dispatch/std",
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"codec/std",
"frame-support/std",
Expand All @@ -50,7 +52,7 @@ std = [
"pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-fee-market/std",
"pallet-bridge-parachains/std",
"pallet-transaction-payment/std",
"scale-info/std",
"sp-api/std",
Expand Down
229 changes: 122 additions & 107 deletions bin/runtime-common/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
use bp_message_dispatch::MessageDispatch as _;
use bp_messages::{
source_chain::LaneMessageVerifier,
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::{DispatchFeePayment, MessageDispatchResult},
messages::{ MessageDispatchResult},
ChainId, Size, StorageProofChecker,
};
use codec::{Decode, DecodeLimit, Encode};
Expand All @@ -39,7 +39,10 @@ use frame_support::{
use hash_db::Hasher;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero},
traits::{
AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Header as HeaderT, Saturating,
Zero,
},
FixedPointNumber, FixedPointOperand, FixedU128,
};
use sp_std::{
Expand Down Expand Up @@ -244,24 +247,6 @@ pub mod source {
pub type ParsedMessagesDeliveryProofFromBridgedChain<B> =
(LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>);

/// Message verifier that is doing all basic checks.
///
/// This verifier assumes following:
///
/// - all message lanes are equivalent, so all checks are the same;
/// - messages are being dispatched using `pallet-bridge-dispatch` pallet on the target chain.
///
/// Following checks are made:
///
/// - message is rejected if its lane is currently blocked;
/// - message is rejected if there are too many pending (undelivered) messages at the outbound
/// lane;
/// - check that the sender has rights to dispatch the call on target chain using provided
/// dispatch origin;
/// - check that the sender has paid enough funds for both message delivery and dispatch.
#[derive(RuntimeDebug)]
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);

/// The error message returned from LaneMessageVerifier when outbound lane is disabled.
pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str =
"The outbound message lane has rejected the message.";
Expand All @@ -273,77 +258,6 @@ pub mod source {
/// The error message returned from LaneMessageVerifier when the message fee is too low.
pub const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane.";

impl<B>
LaneMessageVerifier<
OriginOf<ThisChain<B>>,
AccountIdOf<ThisChain<B>>,
FromThisChainMessagePayload<B>,
BalanceOf<ThisChain<B>>,
> for FromThisChainMessageVerifier<B>
where
B: MessageBridge,
// matches requirements from the `frame_system::Config::Origin`
OriginOf<ThisChain<B>>: Clone
+ Into<Result<frame_system::RawOrigin<AccountIdOf<ThisChain<B>>>, OriginOf<ThisChain<B>>>>,
AccountIdOf<ThisChain<B>>: PartialEq + Clone,
{
type Error = &'static str;

#[allow(clippy::single_match)]
fn verify_message(
submitter: &OriginOf<ThisChain<B>>,
delivery_and_dispatch_fee: &BalanceOf<ThisChain<B>>,
lane: &LaneId,
lane_outbound_data: &OutboundLaneData,
payload: &FromThisChainMessagePayload<B>,
) -> Result<(), Self::Error> {
// reject message if lane is blocked
if !ThisChain::<B>::is_message_accepted(submitter, lane) {
return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE);
}

// reject message if there are too many pending messages at this lane
let max_pending_messages = ThisChain::<B>::maximal_pending_messages_at_outbound_lane();
let pending_messages = lane_outbound_data
.latest_generated_nonce
.saturating_sub(lane_outbound_data.latest_received_nonce);
if pending_messages > max_pending_messages {
return Err(TOO_MANY_PENDING_MESSAGES);
}

// Do the dispatch-specific check. We assume that the target chain uses
// `Dispatch`, so we verify the message accordingly.
let raw_origin_or_err: Result<
frame_system::RawOrigin<AccountIdOf<ThisChain<B>>>,
OriginOf<ThisChain<B>>,
> = submitter.clone().into();
if let Ok(raw_origin) = raw_origin_or_err {
pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload)
.map(drop)
.map_err(|_| BAD_ORIGIN)?;
} else {
// so what it means that we've failed to convert origin to the
// `frame_system::RawOrigin`? now it means that the custom pallet origin has
// been used to send the message. Do we need to verify it? The answer is no,
// because pallet may craft any origin (e.g. root) && we can't verify whether it
// is valid, or not.
};

let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::<B>(
payload,
B::RELAYER_FEE_PERCENT,
None,
)?;

// compare with actual fee paid
if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens {
return Err(TOO_LOW_FEE);
}

Ok(())
}
}

/// Return maximal message size of This -> Bridged chain message.
pub fn maximal_message_size<B: MessageBridge>() -> u32 {
super::target::maximal_incoming_message_size(BridgedChain::<B>::maximal_extrinsic_size())
Expand Down Expand Up @@ -380,6 +294,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>
Expand All @@ -396,23 +313,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.
Expand Down Expand Up @@ -566,7 +530,7 @@ pub mod target {
fn from(encoded_call: FromBridgedChainEncodedMessageCall<DecodedCall>) -> Self {
DecodedCall::decode_with_depth_limit(
sp_api::MAX_EXTRINSIC_DEPTH,
&mut &encoded_call.encoded_call[..],
&mut &encoded_call.encoded_call[..],
)
.map_err(drop)
}
Expand All @@ -584,6 +548,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.
Expand Down Expand Up @@ -618,6 +585,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,
Expand Down
Loading

0 comments on commit fea209c

Please sign in to comment.