bp_messages/target_chain.rs
1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
16
17//! Primitives of messages module, that are used on the target chain.
18
19use crate::{Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData};
20
21use bp_runtime::{messages::MessageDispatchResult, raw_storage_proof_size, RawStorageProof, Size};
22use codec::{Decode, DecodeWithMemTracking, Encode, Error as CodecError};
23use frame_support::weights::Weight;
24use scale_info::TypeInfo;
25use sp_core::RuntimeDebug;
26use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
27
28/// Messages proof from bridged chain.
29///
30/// It contains everything required to prove that bridged (source) chain has
31/// sent us some messages:
32///
33/// - hash of finalized header;
34///
35/// - storage proof of messages and (optionally) outbound lane state;
36///
37/// - lane id;
38///
39/// - nonces (inclusive range) of messages which are included in this proof.
40#[derive(Clone, Decode, DecodeWithMemTracking, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
41pub struct FromBridgedChainMessagesProof<BridgedHeaderHash, Lane> {
42 /// Hash of the finalized bridged header the proof is for.
43 pub bridged_header_hash: BridgedHeaderHash,
44 /// A storage trie proof of messages being delivered.
45 pub storage_proof: RawStorageProof,
46 /// Messages in this proof are sent over this lane.
47 pub lane: Lane,
48 /// Nonce of the first message being delivered.
49 pub nonces_start: MessageNonce,
50 /// Nonce of the last message being delivered.
51 pub nonces_end: MessageNonce,
52}
53
54impl<BridgedHeaderHash, Lane> Size for FromBridgedChainMessagesProof<BridgedHeaderHash, Lane> {
55 fn size(&self) -> u32 {
56 use frame_support::sp_runtime::SaturatedConversion;
57 raw_storage_proof_size(&self.storage_proof).saturated_into()
58 }
59}
60
61/// Proved messages from the source chain.
62pub type ProvedMessages<LaneId, Message> = (LaneId, ProvedLaneMessages<Message>);
63
64/// Proved messages from single lane of the source chain.
65#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
66pub struct ProvedLaneMessages<Message> {
67 /// Optional outbound lane state.
68 pub lane_state: Option<OutboundLaneData>,
69 /// Messages sent through this lane.
70 pub messages: Vec<Message>,
71}
72
73/// Message data with decoded dispatch payload.
74#[derive(RuntimeDebug)]
75pub struct DispatchMessageData<DispatchPayload> {
76 /// Result of dispatch payload decoding.
77 pub payload: Result<DispatchPayload, CodecError>,
78}
79
80/// Message with decoded dispatch payload.
81#[derive(RuntimeDebug)]
82pub struct DispatchMessage<DispatchPayload, LaneId: Encode> {
83 /// Message key.
84 pub key: MessageKey<LaneId>,
85 /// Message data with decoded dispatch payload.
86 pub data: DispatchMessageData<DispatchPayload>,
87}
88
89/// Called when inbound message is received.
90pub trait MessageDispatch {
91 /// Decoded message payload type. Valid message may contain invalid payload. In this case
92 /// message is delivered, but dispatch fails. Therefore, two separate types of payload
93 /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch).
94 type DispatchPayload: Decode;
95
96 /// Fine-grained result of single message dispatch (for better diagnostic purposes)
97 type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq;
98
99 /// Lane identifier type.
100 type LaneId: Encode;
101
102 /// Returns `true` if dispatcher is ready to accept additional messages. The `false` should
103 /// be treated as a hint by both dispatcher and its consumers - i.e. dispatcher shall not
104 /// simply drop messages if it returns `false`. The consumer may still call the `dispatch`
105 /// if dispatcher has returned `false`.
106 ///
107 /// We check it in the messages delivery transaction prologue. So if it becomes `false`
108 /// after some portion of messages is already dispatched, it doesn't fail the whole transaction.
109 fn is_active(lane: Self::LaneId) -> bool;
110
111 /// Estimate dispatch weight.
112 ///
113 /// This function must return correct upper bound of dispatch weight. The return value
114 /// of this function is expected to match return value of the corresponding
115 /// `From<Chain>InboundLaneApi::message_details().dispatch_weight` call.
116 fn dispatch_weight(
117 message: &mut DispatchMessage<Self::DispatchPayload, Self::LaneId>,
118 ) -> Weight;
119
120 /// Called when inbound message is received.
121 ///
122 /// It is up to the implementers of this trait to determine whether the message
123 /// is invalid (i.e. improperly encoded, has too large weight, ...) or not.
124 fn dispatch(
125 message: DispatchMessage<Self::DispatchPayload, Self::LaneId>,
126 ) -> MessageDispatchResult<Self::DispatchLevelResult>;
127}
128
129/// Manages payments that are happening at the target chain during message delivery transaction.
130pub trait DeliveryPayments<AccountId> {
131 /// Error type.
132 type Error: Debug + Into<&'static str>;
133
134 /// Pay rewards for delivering messages to the given relayer.
135 ///
136 /// This method is called during message delivery transaction which has been submitted
137 /// by the `relayer`. The transaction brings `total_messages` messages but only
138 /// `valid_messages` have been accepted. The post-dispatch transaction weight is the
139 /// `actual_weight`.
140 fn pay_reward(
141 relayer: AccountId,
142 total_messages: MessageNonce,
143 valid_messages: MessageNonce,
144 actual_weight: Weight,
145 );
146}
147
148impl<Message> Default for ProvedLaneMessages<Message> {
149 fn default() -> Self {
150 ProvedLaneMessages { lane_state: None, messages: Vec::new() }
151 }
152}
153
154impl<DispatchPayload: Decode, LaneId: Encode> From<Message<LaneId>>
155 for DispatchMessage<DispatchPayload, LaneId>
156{
157 fn from(message: Message<LaneId>) -> Self {
158 DispatchMessage { key: message.key, data: message.payload.into() }
159 }
160}
161
162impl<DispatchPayload: Decode> From<MessagePayload> for DispatchMessageData<DispatchPayload> {
163 fn from(payload: MessagePayload) -> Self {
164 DispatchMessageData { payload: DispatchPayload::decode(&mut &payload[..]) }
165 }
166}
167
168impl<AccountId> DeliveryPayments<AccountId> for () {
169 type Error = &'static str;
170
171 fn pay_reward(
172 _relayer: AccountId,
173 _total_messages: MessageNonce,
174 _valid_messages: MessageNonce,
175 _actual_weight: Weight,
176 ) {
177 // this implementation is not rewarding relayer at all
178 }
179}
180
181/// Structure that may be used in place of `MessageDispatch` on chains,
182/// where inbound messages are forbidden.
183pub struct ForbidInboundMessages<DispatchPayload, LaneId>(PhantomData<(DispatchPayload, LaneId)>);
184
185impl<DispatchPayload: Decode, LaneId: Encode> MessageDispatch
186 for ForbidInboundMessages<DispatchPayload, LaneId>
187{
188 type DispatchPayload = DispatchPayload;
189 type DispatchLevelResult = ();
190 type LaneId = LaneId;
191
192 fn is_active(_: LaneId) -> bool {
193 false
194 }
195
196 fn dispatch_weight(
197 _message: &mut DispatchMessage<Self::DispatchPayload, Self::LaneId>,
198 ) -> Weight {
199 Weight::MAX
200 }
201
202 fn dispatch(
203 _: DispatchMessage<Self::DispatchPayload, Self::LaneId>,
204 ) -> MessageDispatchResult<Self::DispatchLevelResult> {
205 MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () }
206 }
207}