bp_messages/call_info.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//! Defines structures related to calls of the `pallet-bridge-messages` pallet.
18
19use crate::{MessageNonce, UnrewardedRelayersState};
20
21use codec::{Decode, Encode};
22use frame_support::weights::Weight;
23use scale_info::TypeInfo;
24use sp_core::RuntimeDebug;
25use sp_std::ops::RangeInclusive;
26
27/// A minimized version of `pallet-bridge-messages::Call` that can be used without a runtime.
28#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
29#[allow(non_camel_case_types)]
30pub enum BridgeMessagesCall<AccountId, MessagesProof, MessagesDeliveryProof> {
31 /// `pallet-bridge-messages::Call::receive_messages_proof`
32 #[codec(index = 2)]
33 receive_messages_proof {
34 /// Account id of relayer at the **bridged** chain.
35 relayer_id_at_bridged_chain: AccountId,
36 /// Messages proof.
37 proof: MessagesProof,
38 /// A number of messages in the proof.
39 messages_count: u32,
40 /// Total dispatch weight of messages in the proof.
41 dispatch_weight: Weight,
42 },
43 /// `pallet-bridge-messages::Call::receive_messages_delivery_proof`
44 #[codec(index = 3)]
45 receive_messages_delivery_proof {
46 /// Messages delivery proof.
47 proof: MessagesDeliveryProof,
48 /// "Digest" of unrewarded relayers state at the bridged chain.
49 relayers_state: UnrewardedRelayersState,
50 },
51}
52
53/// Generic info about a messages delivery/confirmation proof.
54#[derive(PartialEq, RuntimeDebug)]
55pub struct BaseMessagesProofInfo<LaneId> {
56 /// Message lane, used by the call.
57 pub lane_id: LaneId,
58 /// Nonces of messages, included in the call.
59 ///
60 /// For delivery transaction, it is nonces of bundled messages. For confirmation
61 /// transaction, it is nonces that are to be confirmed during the call.
62 pub bundled_range: RangeInclusive<MessageNonce>,
63 /// Nonce of the best message, stored by this chain before the call is dispatched.
64 ///
65 /// For delivery transaction, it is the nonce of best delivered message before the call.
66 /// For confirmation transaction, it is the nonce of best confirmed message before the call.
67 pub best_stored_nonce: MessageNonce,
68}
69
70impl<LaneId> BaseMessagesProofInfo<LaneId> {
71 /// Returns true if `bundled_range` continues the `0..=best_stored_nonce` range.
72 pub fn appends_to_stored_nonce(&self) -> bool {
73 Some(*self.bundled_range.start()) == self.best_stored_nonce.checked_add(1)
74 }
75}
76
77/// Occupation state of the unrewarded relayers vector.
78#[derive(PartialEq, RuntimeDebug)]
79#[cfg_attr(test, derive(Default))]
80pub struct UnrewardedRelayerOccupation {
81 /// The number of remaining unoccupied entries for new relayers.
82 pub free_relayer_slots: MessageNonce,
83 /// The number of messages that we are ready to accept.
84 pub free_message_slots: MessageNonce,
85}
86
87/// Info about a `ReceiveMessagesProof` call which tries to update a single lane.
88#[derive(PartialEq, RuntimeDebug)]
89pub struct ReceiveMessagesProofInfo<LaneId> {
90 /// Base messages proof info
91 pub base: BaseMessagesProofInfo<LaneId>,
92 /// State of unrewarded relayers vector.
93 pub unrewarded_relayers: UnrewardedRelayerOccupation,
94}
95
96impl<LaneId> ReceiveMessagesProofInfo<LaneId> {
97 /// Returns true if:
98 ///
99 /// - either inbound lane is ready to accept bundled messages;
100 ///
101 /// - or there are no bundled messages, but the inbound lane is blocked by too many unconfirmed
102 /// messages and/or unrewarded relayers.
103 pub fn is_obsolete(&self, is_dispatcher_active: bool) -> bool {
104 // if dispatcher is inactive, we don't accept any delivery transactions
105 if !is_dispatcher_active {
106 return true
107 }
108
109 // transactions with zero bundled nonces are not allowed, unless they're message
110 // delivery transactions, which brings reward confirmations required to unblock
111 // the lane
112 if self.base.bundled_range.is_empty() {
113 let empty_transactions_allowed =
114 // we allow empty transactions when we can't accept delivery from new relayers
115 self.unrewarded_relayers.free_relayer_slots == 0 ||
116 // or if we can't accept new messages at all
117 self.unrewarded_relayers.free_message_slots == 0;
118
119 return !empty_transactions_allowed
120 }
121
122 // otherwise we require bundled messages to continue stored range
123 !self.base.appends_to_stored_nonce()
124 }
125}
126
127/// Info about a `ReceiveMessagesDeliveryProof` call which tries to update a single lane.
128#[derive(PartialEq, RuntimeDebug)]
129pub struct ReceiveMessagesDeliveryProofInfo<LaneId>(pub BaseMessagesProofInfo<LaneId>);
130
131impl<LaneId> ReceiveMessagesDeliveryProofInfo<LaneId> {
132 /// Returns true if outbound lane is ready to accept confirmations of bundled messages.
133 pub fn is_obsolete(&self) -> bool {
134 self.0.bundled_range.is_empty() || !self.0.appends_to_stored_nonce()
135 }
136}
137
138/// Info about a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call
139/// which tries to update a single lane.
140#[derive(PartialEq, RuntimeDebug)]
141pub enum MessagesCallInfo<LaneId: Clone + Copy> {
142 /// Messages delivery call info.
143 ReceiveMessagesProof(ReceiveMessagesProofInfo<LaneId>),
144 /// Messages delivery confirmation call info.
145 ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo<LaneId>),
146}
147
148impl<LaneId: Clone + Copy> MessagesCallInfo<LaneId> {
149 /// Returns lane, used by the call.
150 pub fn lane_id(&self) -> LaneId {
151 match *self {
152 Self::ReceiveMessagesProof(ref info) => info.base.lane_id,
153 Self::ReceiveMessagesDeliveryProof(ref info) => info.0.lane_id,
154 }
155 }
156
157 /// Returns range of messages, bundled with the call.
158 pub fn bundled_messages(&self) -> RangeInclusive<MessageNonce> {
159 match *self {
160 Self::ReceiveMessagesProof(ref info) => info.base.bundled_range.clone(),
161 Self::ReceiveMessagesDeliveryProof(ref info) => info.0.bundled_range.clone(),
162 }
163 }
164}