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