mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 12:51:02 +00:00
BridgeHubRococo/Wococo nits + updated subtree (#2572)
* Nits (merge before separatelly) * Small cosmetics for Rococo/Wococo bridge local run * Squashed 'bridges/' changes from 04b3dda6aa..5fc377ab34 5fc377ab34 Support for kusama-polkadot relaying (#2128) 01f4b7f1ba Fix clippy warnings (#2127) 696ff1c368 BHK/P alignments (#2115) 2a66aa3248 Small fixes (#2126) 7810f1a988 Cosmetics (#2124) daf250f69c Remove some `expect()` statements (#2123) 1c5fba8274 temporarily remove balance guard (#2121) 3d0e547361 Propagate message receival confirmation errors (#2116) 1c33143f07 Propagate message verification errors (#2114) b075b00910 Bump time from 0.3.20 to 0.3.21 51a3a51618 Bump serde from 1.0.160 to 1.0.162 da88d044a6 Bump clap from 4.2.5 to 4.2.7 cdca322cd6 Bump sysinfo from 0.28.4 to 0.29.0 git-subtree-dir: bridges git-subtree-split: 5fc377ab34f7dfd3293099c5feec49255e827812 * Fix * Allow to change storage constants (DeliveryReward, RequiredStakeForStakeAndSlash) + tests * Clippy * New SA for RO/WO * Squashed 'bridges/' changes from 5fc377ab34..0f6091d481 0f6091d481 Bump polkadot/substrate (#2134) 9233f0a337 Bump tokio from 1.28.0 to 1.28.1 a29c1caa93 Bump serde from 1.0.162 to 1.0.163 git-subtree-dir: bridges git-subtree-split: 0f6091d48184ebb4f75cb3089befa6b92cf37335
This commit is contained in:
@@ -14,6 +14,7 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
# Bridge dependencies
|
||||
|
||||
bp-runtime = { path = "../runtime", default-features = false }
|
||||
bp-header-chain = { path = "../header-chain", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
@@ -29,6 +30,7 @@ hex-literal = "0.4"
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-runtime/std",
|
||||
"bp-header-chain/std",
|
||||
"codec/std",
|
||||
"frame-support/std",
|
||||
"scale-info/std",
|
||||
|
||||
@@ -20,9 +20,15 @@
|
||||
// RuntimeApi generated functions
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bp_runtime::{BasicOperatingMode, OperatingMode, RangeInclusiveExt};
|
||||
use bp_header_chain::HeaderChainError;
|
||||
use bp_runtime::{
|
||||
messages::MessageDispatchResult, BasicOperatingMode, OperatingMode, RangeInclusiveExt,
|
||||
StorageProofError,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::RuntimeDebug;
|
||||
use frame_support::{PalletError, RuntimeDebug};
|
||||
// Weight is reexported to avoid additional frame-support dependencies in related crates.
|
||||
pub use frame_support::weights::Weight;
|
||||
use scale_info::TypeInfo;
|
||||
use source_chain::RelayersRewards;
|
||||
use sp_core::TypeId;
|
||||
@@ -32,10 +38,6 @@ pub mod source_chain;
|
||||
pub mod storage_keys;
|
||||
pub mod target_chain;
|
||||
|
||||
use bp_runtime::messages::MessageDispatchResult;
|
||||
// Weight is reexported to avoid additional frame-support dependencies in related crates.
|
||||
pub use frame_support::weights::Weight;
|
||||
|
||||
/// Messages pallet operating mode.
|
||||
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
|
||||
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
|
||||
@@ -189,6 +191,17 @@ impl<RelayerId> InboundLaneData<RelayerId> {
|
||||
.map(|entry| entry.messages.end)
|
||||
.unwrap_or(self.last_confirmed_nonce)
|
||||
}
|
||||
|
||||
/// Returns the total number of messages in the `relayers` vector,
|
||||
/// saturating in case of underflow or overflow.
|
||||
pub fn total_unrewarded_messages(&self) -> MessageNonce {
|
||||
let relayers = &self.relayers;
|
||||
match (relayers.front(), relayers.back()) {
|
||||
(Some(front), Some(back)) =>
|
||||
(front.messages.begin..=back.messages.end).saturating_len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Outbound message details, returned by runtime APIs.
|
||||
@@ -285,7 +298,7 @@ impl DeliveredMessages {
|
||||
|
||||
/// Return total count of delivered messages.
|
||||
pub fn total_messages(&self) -> MessageNonce {
|
||||
(self.begin..=self.end).checked_len().unwrap_or(0)
|
||||
(self.begin..=self.end).saturating_len()
|
||||
}
|
||||
|
||||
/// Note new dispatched message.
|
||||
@@ -316,6 +329,13 @@ pub struct UnrewardedRelayersState {
|
||||
pub last_delivered_nonce: MessageNonce,
|
||||
}
|
||||
|
||||
impl UnrewardedRelayersState {
|
||||
// Verify that the relayers state corresponds with the `InboundLaneData`.
|
||||
pub fn is_valid<RelayerId>(&self, lane_data: &InboundLaneData<RelayerId>) -> bool {
|
||||
self == &lane_data.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<RelayerId> From<&InboundLaneData<RelayerId>> for UnrewardedRelayersState {
|
||||
fn from(lane: &InboundLaneData<RelayerId>) -> UnrewardedRelayersState {
|
||||
UnrewardedRelayersState {
|
||||
@@ -323,9 +343,9 @@ impl<RelayerId> From<&InboundLaneData<RelayerId>> for UnrewardedRelayersState {
|
||||
messages_in_oldest_entry: lane
|
||||
.relayers
|
||||
.front()
|
||||
.and_then(|entry| (entry.messages.begin..=entry.messages.end).checked_len())
|
||||
.map(|entry| entry.messages.total_messages())
|
||||
.unwrap_or(0),
|
||||
total_messages: total_unrewarded_messages(&lane.relayers).unwrap_or(MessageNonce::MAX),
|
||||
total_messages: lane.total_unrewarded_messages(),
|
||||
last_delivered_nonce: lane.last_delivered_nonce(),
|
||||
}
|
||||
}
|
||||
@@ -355,24 +375,6 @@ impl Default for OutboundLaneData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns total number of messages in the `InboundLaneData::relayers` vector.
|
||||
///
|
||||
/// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`).
|
||||
pub fn total_unrewarded_messages<RelayerId>(
|
||||
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
|
||||
) -> Option<MessageNonce> {
|
||||
match (relayers.front(), relayers.back()) {
|
||||
(Some(front), Some(back)) => {
|
||||
if let Some(difference) = back.messages.end.checked_sub(front.messages.begin) {
|
||||
difference.checked_add(1)
|
||||
} else {
|
||||
Some(0)
|
||||
}
|
||||
},
|
||||
_ => Some(0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the number of messages that the relayers have delivered.
|
||||
pub fn calc_relayers_rewards<AccountId>(
|
||||
messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
||||
@@ -414,26 +416,50 @@ pub enum BridgeMessagesCall<AccountId, MessagesProof, MessagesDeliveryProof> {
|
||||
},
|
||||
}
|
||||
|
||||
/// Error that happens during message verification.
|
||||
#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
|
||||
pub enum VerificationError {
|
||||
/// The message proof is empty.
|
||||
EmptyMessageProof,
|
||||
/// Error returned by the bridged header chain.
|
||||
HeaderChain(HeaderChainError),
|
||||
/// Error returned while reading/decoding inbound lane data from the storage proof.
|
||||
InboundLaneStorage(StorageProofError),
|
||||
/// The declared message weight is incorrect.
|
||||
InvalidMessageWeight,
|
||||
/// Declared messages count doesn't match actual value.
|
||||
MessagesCountMismatch,
|
||||
/// Error returned while reading/decoding message data from the storage proof.
|
||||
MessageStorage(StorageProofError),
|
||||
/// The message is too large.
|
||||
MessageTooLarge,
|
||||
/// Error returned while reading/decoding outbound lane data from the storage proof.
|
||||
OutboundLaneStorage(StorageProofError),
|
||||
/// Storage proof related error.
|
||||
StorageProof(StorageProofError),
|
||||
/// Custom error
|
||||
Other(#[codec(skip)] &'static str),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn total_unrewarded_messages_does_not_overflow() {
|
||||
assert_eq!(
|
||||
total_unrewarded_messages(
|
||||
&vec![
|
||||
UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) },
|
||||
UnrewardedRelayer {
|
||||
relayer: 2,
|
||||
messages: DeliveredMessages::new(MessageNonce::MAX)
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.collect()
|
||||
),
|
||||
None,
|
||||
);
|
||||
let lane_data = InboundLaneData {
|
||||
relayers: vec![
|
||||
UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) },
|
||||
UnrewardedRelayer {
|
||||
relayer: 2,
|
||||
messages: DeliveredMessages::new(MessageNonce::MAX),
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
last_confirmed_nonce: 0,
|
||||
};
|
||||
assert_eq!(lane_data.total_unrewarded_messages(), MessageNonce::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Primitives of messages module, that are used on the source chain.
|
||||
|
||||
use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData};
|
||||
use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, VerificationError};
|
||||
|
||||
use crate::UnrewardedRelayer;
|
||||
use bp_runtime::Size;
|
||||
@@ -40,9 +40,6 @@ pub type RelayersRewards<AccountId> = BTreeMap<AccountId, MessageNonce>;
|
||||
/// source chain to the target chain. The `AccountId` type here means the account
|
||||
/// type used by the source chain.
|
||||
pub trait TargetHeaderChain<Payload, AccountId> {
|
||||
/// Error type.
|
||||
type Error: Debug;
|
||||
|
||||
/// Proof that messages have been received by target chain.
|
||||
type MessagesDeliveryProof: Parameter + Size;
|
||||
|
||||
@@ -58,12 +55,12 @@ pub trait TargetHeaderChain<Payload, AccountId> {
|
||||
/// 1MB. BTC nodes aren't accepting transactions that are larger than 1MB, so relayer
|
||||
/// will be unable to craft valid transaction => this (and all subsequent) messages will
|
||||
/// never be delivered.
|
||||
fn verify_message(payload: &Payload) -> Result<(), Self::Error>;
|
||||
fn verify_message(payload: &Payload) -> Result<(), VerificationError>;
|
||||
|
||||
/// Verify messages delivery proof and return lane && nonce of the latest received message.
|
||||
fn verify_messages_delivery_proof(
|
||||
proof: Self::MessagesDeliveryProof,
|
||||
) -> Result<(LaneId, InboundLaneData<AccountId>), Self::Error>;
|
||||
) -> Result<(LaneId, InboundLaneData<AccountId>), VerificationError>;
|
||||
}
|
||||
|
||||
/// Lane message verifier.
|
||||
@@ -75,9 +72,6 @@ pub trait TargetHeaderChain<Payload, AccountId> {
|
||||
///
|
||||
/// Any fee requirements should also be enforced here.
|
||||
pub trait LaneMessageVerifier<SenderOrigin, Payload> {
|
||||
/// Error type.
|
||||
type Error: Debug + Into<&'static str>;
|
||||
|
||||
/// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the
|
||||
/// lane.
|
||||
fn verify_message(
|
||||
@@ -85,7 +79,7 @@ pub trait LaneMessageVerifier<SenderOrigin, Payload> {
|
||||
lane: &LaneId,
|
||||
outbound_data: &OutboundLaneData,
|
||||
payload: &Payload,
|
||||
) -> Result<(), Self::Error>;
|
||||
) -> Result<(), VerificationError>;
|
||||
}
|
||||
|
||||
/// Manages payments that are happening at the source chain during delivery confirmation
|
||||
@@ -169,31 +163,27 @@ const ALL_OUTBOUND_MESSAGES_REJECTED: &str =
|
||||
"This chain is configured to reject all outbound messages";
|
||||
|
||||
impl<Payload, AccountId> TargetHeaderChain<Payload, AccountId> for ForbidOutboundMessages {
|
||||
type Error = &'static str;
|
||||
|
||||
type MessagesDeliveryProof = ();
|
||||
|
||||
fn verify_message(_payload: &Payload) -> Result<(), Self::Error> {
|
||||
Err(ALL_OUTBOUND_MESSAGES_REJECTED)
|
||||
fn verify_message(_payload: &Payload) -> Result<(), VerificationError> {
|
||||
Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED))
|
||||
}
|
||||
|
||||
fn verify_messages_delivery_proof(
|
||||
_proof: Self::MessagesDeliveryProof,
|
||||
) -> Result<(LaneId, InboundLaneData<AccountId>), Self::Error> {
|
||||
Err(ALL_OUTBOUND_MESSAGES_REJECTED)
|
||||
) -> Result<(LaneId, InboundLaneData<AccountId>), VerificationError> {
|
||||
Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED))
|
||||
}
|
||||
}
|
||||
|
||||
impl<SenderOrigin, Payload> LaneMessageVerifier<SenderOrigin, Payload> for ForbidOutboundMessages {
|
||||
type Error = &'static str;
|
||||
|
||||
fn verify_message(
|
||||
_submitter: &SenderOrigin,
|
||||
_lane: &LaneId,
|
||||
_outbound_data: &OutboundLaneData,
|
||||
_payload: &Payload,
|
||||
) -> Result<(), Self::Error> {
|
||||
Err(ALL_OUTBOUND_MESSAGES_REJECTED)
|
||||
) -> Result<(), VerificationError> {
|
||||
Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
//! Primitives of messages module, that are used on the target chain.
|
||||
|
||||
use crate::{LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData};
|
||||
use crate::{
|
||||
LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, VerificationError,
|
||||
};
|
||||
|
||||
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||
use codec::{Decode, Encode, Error as CodecError};
|
||||
@@ -58,9 +60,6 @@ pub struct DispatchMessage<DispatchPayload> {
|
||||
/// can't change. Wrong implementation may lead to invalid lane states (i.e. lane
|
||||
/// that's stuck) and/or processing messages without paying fees.
|
||||
pub trait SourceHeaderChain {
|
||||
/// Error type.
|
||||
type Error: Debug;
|
||||
|
||||
/// Proof that messages are sent from source chain. This may also include proof
|
||||
/// of corresponding outbound lane states.
|
||||
type MessagesProof: Parameter + Size;
|
||||
@@ -79,7 +78,7 @@ pub trait SourceHeaderChain {
|
||||
fn verify_messages_proof(
|
||||
proof: Self::MessagesProof,
|
||||
messages_count: u32,
|
||||
) -> Result<ProvedMessages<Message>, Self::Error>;
|
||||
) -> Result<ProvedMessages<Message>, VerificationError>;
|
||||
}
|
||||
|
||||
/// Called when inbound message is received.
|
||||
@@ -164,21 +163,20 @@ pub struct ForbidInboundMessages<MessagesProof, DispatchPayload>(
|
||||
PhantomData<(MessagesProof, DispatchPayload)>,
|
||||
);
|
||||
|
||||
/// Error message that is used in `ForbidOutboundMessages` implementation.
|
||||
/// Error message that is used in `ForbidInboundMessages` implementation.
|
||||
const ALL_INBOUND_MESSAGES_REJECTED: &str =
|
||||
"This chain is configured to reject all inbound messages";
|
||||
|
||||
impl<MessagesProof: Parameter + Size, DispatchPayload> SourceHeaderChain
|
||||
for ForbidInboundMessages<MessagesProof, DispatchPayload>
|
||||
{
|
||||
type Error = &'static str;
|
||||
type MessagesProof = MessagesProof;
|
||||
|
||||
fn verify_messages_proof(
|
||||
_proof: Self::MessagesProof,
|
||||
_messages_count: u32,
|
||||
) -> Result<ProvedMessages<Message>, Self::Error> {
|
||||
Err(ALL_INBOUND_MESSAGES_REJECTED)
|
||||
) -> Result<ProvedMessages<Message>, VerificationError> {
|
||||
Err(VerificationError::Other(ALL_INBOUND_MESSAGES_REJECTED))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user