From 3d24a4e34e9205ac5aad535e620456cc7bb42720 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 07:05:05 +0300 Subject: [PATCH] verify messages delivery proofs (#482) --- .../bin/millau/runtime/src/rialto_messages.rs | 17 ++++--- .../bin/rialto/runtime/src/millau_messages.rs | 12 +++-- bridges/bin/runtime-common/Cargo.toml | 2 + bridges/bin/runtime-common/src/messages.rs | 49 ++++++++++++++++++- 4 files changed, 67 insertions(+), 13 deletions(-) diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 450d38b6d0..fc20cf7b56 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -30,7 +30,6 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; -use sp_trie::StorageProof; /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -63,6 +62,12 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifie /// Message payload for Rialto -> Millau messages. pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +/// Messages proof for Rialto -> Millau messages. +type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; + +/// Messages delivery proof for Millau -> Rialto messages. +type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; + /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoMessageBridge, @@ -152,7 +157,7 @@ impl TargetHeaderChain for Rialto // - 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 = (bp_rialto::Hash, StorageProof, LaneId); + type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { if payload.weight > WithRialtoMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { @@ -163,9 +168,9 @@ impl TargetHeaderChain for Rialto } fn verify_messages_delivery_proof( - _proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof::(proof) } } @@ -176,7 +181,7 @@ impl SourceHeaderChain for Rialto { // - 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 = (bp_rialto::Hash, StorageProof, LaneId, MessageNonce, MessageNonce); + type MessagesProof = FromRialtoMessagesProof; fn verify_messages_proof( _proof: Self::MessagesProof, diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 97067078e3..79b03ba935 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -30,7 +30,6 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; -use sp_trie::StorageProof; /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -73,6 +72,9 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi /// Messages proof for Millau -> Rialto messages. type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; +/// Messages delivery proof for Rialto -> Millau messages. +type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; + /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithMillauMessageBridge; @@ -155,7 +157,7 @@ impl TargetHeaderChain for Millau // - 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 = (bp_millau::Hash, StorageProof, LaneId); + type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { if payload.weight > WithMillauMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { @@ -166,9 +168,9 @@ impl TargetHeaderChain for Millau } fn verify_messages_delivery_proof( - _proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof::(proof) } } diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index 61d4928da3..93e0bf6a2b 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -17,6 +17,7 @@ bp-message-lane = { path = "../../primitives/message-lane", default-features = f bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } pallet-message-lane = { path = "../../modules/message-lane", default-features = false } +pallet-substrate-bridge = { path = "../../modules/substrate", default-features = false } # Substrate dependencies @@ -35,6 +36,7 @@ std = [ "frame-support/std", "pallet-bridge-call-dispatch/std", "pallet-message-lane/std", + "pallet-substrate-bridge/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index 9ac6ced189..384b17e44a 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -24,7 +24,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_message_lane::{ source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch}, - LaneId, MessageNonce, + InboundLaneData, LaneId, MessageNonce, }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; @@ -77,7 +77,7 @@ pub trait ChainWithMessageLanes { /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. - type AccountId; + type AccountId: Decode; /// Public key of the chain account that may be used to verify signatures. type Signer: Decode; /// Signature type used on the chain. @@ -105,6 +105,7 @@ pub(crate) type SignatureOf = ::Signature; pub(crate) type WeightOf = ::Weight; pub(crate) type BalanceOf = ::Balance; pub(crate) type CallOf = ::Call; +pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { @@ -121,6 +122,16 @@ pub mod source { BridgedChainOpaqueCall, >; + /// Messages delivery proof from bridged chain: + /// + /// - hash of finalized header; + /// - storage proof of inbound lane state; + /// - lane id. + pub type FromBridgedChainMessagesDeliveryProof = (HashOf>, StorageProof, LaneId); + + /// 'Parsed' message delivery proof - inbound lane id and its state. + pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); + /// Message verifier that requires submitter to pay minimal delivery and dispatch fee. #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); @@ -188,6 +199,40 @@ pub mod source { .and_then(|interest| fee.checked_add(&interest))) .ok_or("Overflow when computing minimal required message delivery and dispatch fee") } + + /// Verify proof of This -> Bridged chain messages delivery. + pub fn verify_messages_delivery_proof( + proof: FromBridgedChainMessagesDeliveryProof, + ) -> Result, &'static str> + where + ThisRuntime: pallet_substrate_bridge::Trait, + ThisRuntime: pallet_message_lane::Trait>>, + HashOf>: + Into::BridgedChain>>, + { + let (bridged_header_hash, bridged_storage_proof, lane) = proof; + pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + bridged_header_hash.into(), + bridged_storage_proof, + |storage| { + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = pallet_message_lane::storage_keys::inbound_lane_data_key::< + ThisRuntime, + MessageLaneInstanceOf>, + >(&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)) + }, + ) + .map_err(<&'static str>::from)? + } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages.