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
+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,