Propagate message verification errors (#2114)

* Propagate message verification errors

* Replace parse_finalized_storage_proof() with storage_proof_checker()

* small fixes

* fix comment
This commit is contained in:
Serban Iorga
2023-05-09 08:21:02 +03:00
committed by Bastian Köcher
parent c490222fc6
commit 56d4013878
10 changed files with 268 additions and 295 deletions
+33 -6
View File
@@ -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))]
@@ -414,6 +416,31 @@ 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::*;
+10 -20
View File
@@ -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))
}
}