Skip to content

Commit

Permalink
moved all call-related definitions to primitives (#2583)
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatonik authored Sep 25, 2023
1 parent 9707727 commit 99da1f9
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 268 deletions.
20 changes: 9 additions & 11 deletions bin/runtime-common/src/refund_relayer_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
//! with calls that are: delivering new messsage and all necessary underlying headers
//! (parachain or relay chain).

use bp_messages::{ChainWithMessages, LaneId, MessageNonce};
use bp_header_chain::SubmitFinalityProofInfo;
use bp_messages::{ChainWithMessages, LaneId, MessageNonce, MessagesCallInfo};
use bp_parachains::SubmitParachainHeadsInfo;
use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
use bp_runtime::{Chain, Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider};
use codec::{Codec, Decode, Encode};
Expand All @@ -31,15 +33,13 @@ use frame_support::{
};
use pallet_bridge_grandpa::{
CallSubType as GrandpaCallSubType, Config as GrandpaConfig, SubmitFinalityProofHelper,
SubmitFinalityProofInfo,
};
use pallet_bridge_messages::{
CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo,
CallSubType as MessagesCallSubType, Config as MessagesConfig,
CallHelper as MessagesCallHelper, CallSubType as MessagesCallSubType, Config as MessagesConfig,
};
use pallet_bridge_parachains::{
BoundedBridgeGrandpaConfig, CallSubType as ParachainsCallSubType, Config as ParachainsConfig,
RelayBlockNumber, SubmitParachainHeadsHelper, SubmitParachainHeadsInfo,
RelayBlockNumber, SubmitParachainHeadsHelper,
};
use pallet_bridge_relayers::{
Config as RelayersConfig, Pallet as RelayersPallet, WeightInfoExt as _,
Expand Down Expand Up @@ -830,8 +830,9 @@ mod tests {
use crate::mock::*;
use bp_messages::{
source_chain::FromBridgedChainMessagesDeliveryProof,
target_chain::FromBridgedChainMessagesProof, InboundLaneData, MessageNonce,
OutboundLaneData, UnrewardedRelayersState,
target_chain::FromBridgedChainMessagesProof, BaseMessagesProofInfo, InboundLaneData,
MessageNonce, OutboundLaneData, ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo,
UnrewardedRelayerOccupation, UnrewardedRelayersState,
};
use bp_parachains::{BestParaHeadHash, ParaInfo};
use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId};
Expand All @@ -843,10 +844,7 @@ mod tests {
weights::Weight,
};
use pallet_bridge_grandpa::{Call as GrandpaCall, StoredAuthoritySet};
use pallet_bridge_messages::{
BaseMessagesProofInfo, Call as MessagesCall, ReceiveMessagesDeliveryProofInfo,
ReceiveMessagesProofInfo, UnrewardedRelayerOccupation,
};
use pallet_bridge_messages::Call as MessagesCall;
use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash};
use sp_runtime::{
traits::{ConstU64, Header as HeaderT},
Expand Down
34 changes: 5 additions & 29 deletions modules/grandpa/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,18 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet};
use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa};
use bp_header_chain::{
justification::GrandpaJustification, ChainWithGrandpa, SubmitFinalityProofInfo,
};
use bp_runtime::BlockNumberOf;
use codec::Encode;
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight};
use sp_runtime::{
traits::{Header, Zero},
traits::Header,
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
RuntimeDebug, SaturatedConversion,
SaturatedConversion,
};

/// Info about a `SubmitParachainHeads` call which tries to update a single parachain.
#[derive(Copy, Clone, PartialEq, RuntimeDebug)]
pub struct SubmitFinalityProofInfo<N> {
/// Number of the finality target.
pub block_number: N,
/// Extra weight that we assume is included in the call.
///
/// We have some assumptions about headers and justifications of the bridged chain.
/// We know that if our assumptions are correct, then the call must not have the
/// weight above some limit. The fee paid for weight above that limit, is never refunded.
pub extra_weight: Weight,
/// Extra size (in bytes) that we assume are included in the call.
///
/// We have some assumptions about headers and justifications of the bridged chain.
/// We know that if our assumptions are correct, then the call must not have the
/// weight above some limit. The fee paid for bytes above that limit, is never refunded.
pub extra_size: u32,
}

impl<N> SubmitFinalityProofInfo<N> {
/// Returns `true` if call size/weight is below our estimations for regular calls.
pub fn fits_limits(&self) -> bool {
self.extra_weight.is_zero() && self.extra_size.is_zero()
}
}

/// Helper struct that provides methods for working with the `SubmitFinalityProof` call.
pub struct SubmitFinalityProofHelper<T: Config<I>, I: 'static> {
_phantom_data: sp_std::marker::PhantomData<(T, I)>,
Expand Down
162 changes: 30 additions & 132 deletions modules/messages/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,119 +20,15 @@
use crate::{BridgedChainOf, Config, InboundLanes, OutboundLanes, Pallet, LOG_TARGET};

use bp_messages::{
target_chain::MessageDispatch, ChainWithMessages, InboundLaneData, LaneId, MessageNonce,
target_chain::MessageDispatch, BaseMessagesProofInfo, ChainWithMessages, InboundLaneData,
LaneId, MessageNonce, MessagesCallInfo, ReceiveMessagesDeliveryProofInfo,
ReceiveMessagesProofInfo, UnrewardedRelayerOccupation,
};
use bp_runtime::AccountIdOf;
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
use sp_runtime::{transaction_validity::TransactionValidity, RuntimeDebug};
use sp_std::ops::RangeInclusive;

/// Generic info about a messages delivery/confirmation proof.
#[derive(PartialEq, RuntimeDebug)]
pub struct BaseMessagesProofInfo {
/// 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 BaseMessagesProofInfo {
/// Returns true if `bundled_range` continues the `0..=best_stored_nonce` range.
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 {
/// Base messages proof info
pub base: BaseMessagesProofInfo,
/// State of unrewarded relayers vector.
pub unrewarded_relayers: UnrewardedRelayerOccupation,
}

impl ReceiveMessagesProofInfo {
/// 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.
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(pub BaseMessagesProofInfo);

impl ReceiveMessagesDeliveryProofInfo {
/// Returns true if outbound lane is ready to accept confirmations of bundled messages.
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 CallInfo {
/// Messages delivery call info.
ReceiveMessagesProof(ReceiveMessagesProofInfo),
/// Messages delivery confirmation call info.
ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo),
}

impl CallInfo {
/// 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(),
}
}
}
use sp_runtime::transaction_validity::TransactionValidity;

/// Helper struct that provides methods for working with a call supported by `CallInfo`.
/// Helper struct that provides methods for working with a call supported by `MessagesCallInfo`.
pub struct CallHelper<T: Config<I>, I: 'static> {
_phantom_data: sp_std::marker::PhantomData<(T, I)>,
}
Expand All @@ -144,9 +40,9 @@ impl<T: Config<I>, I: 'static> CallHelper<T, I> {
///
/// - call is `receive_messages_delivery_proof` and all messages confirmations have been
/// received.
pub fn was_successful(info: &CallInfo) -> bool {
pub fn was_successful(info: &MessagesCallInfo) -> bool {
match info {
CallInfo::ReceiveMessagesProof(info) => {
MessagesCallInfo::ReceiveMessagesProof(info) => {
let inbound_lane_data = match InboundLanes::<T, I>::get(info.base.lane_id) {
Some(inbound_lane_data) => inbound_lane_data,
None => return false,
Expand All @@ -164,7 +60,7 @@ impl<T: Config<I>, I: 'static> CallHelper<T, I> {

inbound_lane_data.last_delivered_nonce() == *info.base.bundled_range.end()
},
CallInfo::ReceiveMessagesDeliveryProof(info) => {
MessagesCallInfo::ReceiveMessagesDeliveryProof(info) => {
let outbound_lane_data = match OutboundLanes::<T, I>::get(info.0.lane_id) {
Some(outbound_lane_data) => outbound_lane_data,
None => return false,
Expand All @@ -186,13 +82,13 @@ pub trait CallSubType<T: Config<I, RuntimeCall = Self>, I: 'static>:
/// a `ReceiveMessagesDeliveryProof` call.
fn receive_messages_delivery_proof_info(&self) -> Option<ReceiveMessagesDeliveryProofInfo>;

/// Create a new instance of `CallInfo` from a `ReceiveMessagesProof`
/// Create a new instance of `MessagesCallInfo` from a `ReceiveMessagesProof`
/// or a `ReceiveMessagesDeliveryProof` call.
fn call_info(&self) -> Option<CallInfo>;
fn call_info(&self) -> Option<MessagesCallInfo>;

/// Create a new instance of `CallInfo` from a `ReceiveMessagesProof`
/// Create a new instance of `MessagesCallInfo` from a `ReceiveMessagesProof`
/// or a `ReceiveMessagesDeliveryProof` call, if the call is for the provided lane.
fn call_info_for(&self, lane_id: LaneId) -> Option<CallInfo>;
fn call_info_for(&self, lane_id: LaneId) -> Option<MessagesCallInfo>;

/// Check that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call is trying
/// to deliver/confirm at least some messages that are better than the ones we know of.
Expand Down Expand Up @@ -250,31 +146,31 @@ impl<
None
}

fn call_info(&self) -> Option<CallInfo> {
fn call_info(&self) -> Option<MessagesCallInfo> {
if let Some(info) = self.receive_messages_proof_info() {
return Some(CallInfo::ReceiveMessagesProof(info))
return Some(MessagesCallInfo::ReceiveMessagesProof(info))
}

if let Some(info) = self.receive_messages_delivery_proof_info() {
return Some(CallInfo::ReceiveMessagesDeliveryProof(info))
return Some(MessagesCallInfo::ReceiveMessagesDeliveryProof(info))
}

None
}

fn call_info_for(&self, lane_id: LaneId) -> Option<CallInfo> {
fn call_info_for(&self, lane_id: LaneId) -> Option<MessagesCallInfo> {
self.call_info().filter(|info| {
let actual_lane_id = match info {
CallInfo::ReceiveMessagesProof(info) => info.base.lane_id,
CallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id,
MessagesCallInfo::ReceiveMessagesProof(info) => info.base.lane_id,
MessagesCallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id,
};
actual_lane_id == lane_id
})
}

fn check_obsolete_call(&self) -> TransactionValidity {
match self.call_info() {
Some(CallInfo::ReceiveMessagesProof(proof_info))
Some(MessagesCallInfo::ReceiveMessagesProof(proof_info))
if proof_info
.is_obsolete(T::MessageDispatch::is_active(proof_info.base.lane_id)) =>
{
Expand All @@ -286,7 +182,7 @@ impl<

return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
},
Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info))
Some(MessagesCallInfo::ReceiveMessagesDeliveryProof(proof_info))
if proof_info.is_obsolete() =>
{
log::trace!(
Expand Down Expand Up @@ -559,7 +455,7 @@ mod tests {
bundled_range: RangeInclusive<MessageNonce>,
is_empty: bool,
) -> bool {
CallHelper::<TestRuntime, ()>::was_successful(&CallInfo::ReceiveMessagesProof(
CallHelper::<TestRuntime, ()>::was_successful(&MessagesCallInfo::ReceiveMessagesProof(
ReceiveMessagesProofInfo {
base: BaseMessagesProofInfo {
lane_id: test_lane_id(),
Expand Down Expand Up @@ -620,13 +516,15 @@ mod tests {
}

fn was_message_confirmation_successful(bundled_range: RangeInclusive<MessageNonce>) -> bool {
CallHelper::<TestRuntime, ()>::was_successful(&CallInfo::ReceiveMessagesDeliveryProof(
ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo {
lane_id: test_lane_id(),
bundled_range,
best_stored_nonce: 0, // doesn't matter for `was_successful`
}),
))
CallHelper::<TestRuntime, ()>::was_successful(
&MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
BaseMessagesProofInfo {
lane_id: test_lane_id(),
bundled_range,
best_stored_nonce: 0, // doesn't matter for `was_successful`
},
)),
)
}

#[test]
Expand Down
21 changes: 3 additions & 18 deletions modules/parachains/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,10 @@
// 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/>.

use crate::{Config, Pallet, RelayBlockNumber};
use bp_parachains::BestParaHeadHash;
use bp_polkadot_core::parachains::{ParaHash, ParaId};
use crate::{Config, Pallet};
use bp_parachains::{BestParaHeadHash, SubmitParachainHeadsInfo};
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
use sp_runtime::{
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
RuntimeDebug,
};

/// Info about a `SubmitParachainHeads` call which tries to update a single parachain.
#[derive(PartialEq, RuntimeDebug)]
pub struct SubmitParachainHeadsInfo {
/// Number of the finalized relay block that has been used to prove parachain finality.
pub at_relay_block_number: RelayBlockNumber,
/// Parachain identifier.
pub para_id: ParaId,
/// Hash of the bundled parachain head.
pub para_head_hash: ParaHash,
}
use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction};

/// Helper struct that provides methods for working with the `SubmitParachainHeads` call.
pub struct SubmitParachainHeadsHelper<T: Config<I>, I: 'static> {
Expand Down
4 changes: 3 additions & 1 deletion modules/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub use weights::WeightInfo;
pub use weights_ext::WeightInfoExt;

use bp_header_chain::{HeaderChain, HeaderChainError};
use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData};
use bp_parachains::{
parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData, SubmitParachainHeadsInfo,
};
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain};
use frame_support::{dispatch::PostDispatchInfo, DefaultNoBound};
Expand Down
Loading

0 comments on commit 99da1f9

Please sign in to comment.