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:
Branislav Kontur
2023-05-17 00:33:30 +02:00
committed by GitHub
parent 90de06876a
commit 17b2e1b300
41 changed files with 770 additions and 619 deletions
@@ -17,8 +17,8 @@
//! Messages pallet benchmarking.
use crate::{
inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane,
weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, OutboundLanes,
inbound_lane::InboundLaneStorage, outbound_lane, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH,
Call, OutboundLanes, RuntimeInboundLaneStorage,
};
use bp_messages::{
@@ -443,11 +443,12 @@ benchmarks_instance_pallet! {
fn send_regular_message<T: Config<I>, I: 'static>() {
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
outbound_lane.send_message(vec![]);
outbound_lane.send_message(vec![]).expect("We craft valid messages");
}
fn receive_messages<T: Config<I>, I: 'static>(nonce: MessageNonce) {
let mut inbound_lane_storage = inbound_lane_storage::<T, I>(T::bench_lane_id());
let mut inbound_lane_storage =
RuntimeInboundLaneStorage::<T, I>::from_lane_id(T::bench_lane_id());
inbound_lane_storage.set_data(InboundLaneData {
relayers: vec![UnrewardedRelayer {
relayer: T::bridged_relayer_id(),
@@ -40,7 +40,7 @@ pub trait InboundLaneStorage {
/// Return maximal number of unconfirmed messages in inbound lane.
fn max_unconfirmed_messages(&self) -> MessageNonce;
/// Get lane data from the storage.
fn data(&self) -> InboundLaneData<Self::Relayer>;
fn get_or_init_data(&mut self) -> InboundLaneData<Self::Relayer>;
/// Update lane data in the storage.
fn set_data(&mut self, data: InboundLaneData<Self::Relayer>);
}
@@ -117,9 +117,9 @@ impl<S: InboundLaneStorage> InboundLane<S> {
InboundLane { storage }
}
/// Returns storage reference.
pub fn storage(&self) -> &S {
&self.storage
/// Returns `mut` storage reference.
pub fn storage_mut(&mut self) -> &mut S {
&mut self.storage
}
/// Receive state of the corresponding outbound lane.
@@ -127,7 +127,7 @@ impl<S: InboundLaneStorage> InboundLane<S> {
&mut self,
outbound_lane_data: OutboundLaneData,
) -> Option<MessageNonce> {
let mut data = self.storage.data();
let mut data = self.storage.get_or_init_data();
let last_delivered_nonce = data.last_delivered_nonce();
if outbound_lane_data.latest_received_nonce > last_delivered_nonce {
@@ -170,9 +170,8 @@ impl<S: InboundLaneStorage> InboundLane<S> {
nonce: MessageNonce,
message_data: DispatchMessageData<Dispatch::DispatchPayload>,
) -> ReceivalResult<Dispatch::DispatchLevelResult> {
let mut data = self.storage.data();
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
if !is_correct_message {
let mut data = self.storage.get_or_init_data();
if Some(nonce) != data.last_delivered_nonce().checked_add(1) {
return ReceivalResult::InvalidNonce
}
@@ -252,7 +251,7 @@ mod tests {
None,
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 0);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 0);
});
}
@@ -270,7 +269,7 @@ mod tests {
}),
Some(3),
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3);
assert_eq!(
lane.receive_state_update(OutboundLaneData {
@@ -279,7 +278,7 @@ mod tests {
}),
None,
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3);
});
}
@@ -290,9 +289,9 @@ mod tests {
receive_regular_message(&mut lane, 1);
receive_regular_message(&mut lane, 2);
receive_regular_message(&mut lane, 3);
assert_eq!(lane.storage.data().last_confirmed_nonce, 0);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 0);
assert_eq!(
lane.storage.data().relayers,
lane.storage.get_or_init_data().relayers,
vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)]
);
@@ -303,9 +302,9 @@ mod tests {
}),
Some(2),
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 2);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 2);
assert_eq!(
lane.storage.data().relayers,
lane.storage.get_or_init_data().relayers,
vec![unrewarded_relayer(3, 3, TEST_RELAYER_A)]
);
@@ -316,8 +315,8 @@ mod tests {
}),
Some(3),
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
assert_eq!(lane.storage.data().relayers, vec![]);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3);
assert_eq!(lane.storage.get_or_init_data().relayers, vec![]);
});
}
@@ -325,7 +324,7 @@ mod tests {
fn receive_status_update_works_with_batches_from_relayers() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let mut seed_storage_data = lane.storage.data();
let mut seed_storage_data = lane.storage.get_or_init_data();
// Prepare data
seed_storage_data.last_confirmed_nonce = 0;
seed_storage_data.relayers.push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A));
@@ -341,9 +340,9 @@ mod tests {
}),
Some(3),
);
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3);
assert_eq!(
lane.storage.data().relayers,
lane.storage.get_or_init_data().relayers,
vec![
unrewarded_relayer(4, 4, TEST_RELAYER_B),
unrewarded_relayer(5, 5, TEST_RELAYER_C)
@@ -364,7 +363,7 @@ mod tests {
),
ReceivalResult::InvalidNonce
);
assert_eq!(lane.storage.data().last_delivered_nonce(), 0);
assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 0);
});
}
@@ -470,7 +469,7 @@ mod tests {
ReceivalResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.storage.data().relayers,
lane.storage.get_or_init_data().relayers,
vec![
unrewarded_relayer(1, 1, TEST_RELAYER_A),
unrewarded_relayer(2, 2, TEST_RELAYER_B),
@@ -508,7 +507,7 @@ mod tests {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
receive_regular_message(&mut lane, 1);
assert_eq!(lane.storage.data().last_delivered_nonce(), 1);
assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 1);
});
}
+80 -118
View File
@@ -48,7 +48,7 @@ pub use weights_ext::{
use crate::{
inbound_lane::{InboundLane, InboundLaneStorage},
outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult},
outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationError},
};
use bp_messages::{
@@ -59,15 +59,15 @@ use bp_messages::{
DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages,
SourceHeaderChain,
},
total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId,
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
OutboundMessageDetails, UnrewardedRelayersState,
DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce,
MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails,
UnrewardedRelayersState, VerificationError,
};
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get};
use sp_runtime::traits::UniqueSaturatedFrom;
use sp_std::{cell::RefCell, marker::PhantomData, prelude::*};
use sp_std::{marker::PhantomData, prelude::*};
mod inbound_lane;
mod outbound_lane;
@@ -319,7 +319,7 @@ pub mod pallet {
// subtract extra storage proof bytes from the actual PoV size - there may be
// less unrewarded relayers than the maximal configured value
let lane_extra_proof_size_bytes = lane.storage().extra_proof_size_bytes();
let lane_extra_proof_size_bytes = lane.storage_mut().extra_proof_size_bytes();
actual_weight = actual_weight.set_proof_size(
actual_weight.proof_size().saturating_sub(lane_extra_proof_size_bytes),
);
@@ -332,7 +332,7 @@ pub mod pallet {
"Received lane {:?} state update: latest_confirmed_nonce={}. Unrewarded relayers: {:?}",
lane_id,
updated_latest_confirmed_nonce,
UnrewardedRelayersState::from(&lane.storage().data()),
UnrewardedRelayersState::from(&lane.storage_mut().get_or_init_data()),
);
}
}
@@ -437,57 +437,21 @@ pub mod pallet {
Error::<T, I>::InvalidMessagesDeliveryProof
})?;
// verify that the relayer has declared correct `lane_data::relayers` state
// (we only care about total number of entries and messages, because this affects call
// weight)
ensure!(
total_unrewarded_messages(&lane_data.relayers).unwrap_or(MessageNonce::MAX) ==
relayers_state.total_messages &&
lane_data.relayers.len() as MessageNonce ==
relayers_state.unrewarded_relayer_entries,
Error::<T, I>::InvalidUnrewardedRelayersState
);
// the `last_delivered_nonce` field may also be used by the signed extension. Even
// though providing wrong value isn't critical, let's also check it here.
ensure!(
lane_data.last_delivered_nonce() == relayers_state.last_delivered_nonce,
relayers_state.is_valid(&lane_data),
Error::<T, I>::InvalidUnrewardedRelayersState
);
// mark messages as delivered
let mut lane = outbound_lane::<T, I>(lane_id);
let last_delivered_nonce = lane_data.last_delivered_nonce();
let confirmed_messages = match lane.confirm_delivery(
relayers_state.total_messages,
last_delivered_nonce,
&lane_data.relayers,
) {
ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) =>
Some(confirmed_messages),
ReceivalConfirmationResult::NoNewConfirmations => None,
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(
to_confirm_messages_count,
) => {
log::trace!(
target: LOG_TARGET,
"Messages delivery proof contains too many messages to confirm: {} vs declared {}",
to_confirm_messages_count,
relayers_state.total_messages,
);
fail!(Error::<T, I>::TryingToConfirmMoreMessagesThanExpected);
},
error => {
log::trace!(
target: LOG_TARGET,
"Messages delivery proof contains invalid unrewarded relayers vec: {:?}",
error,
);
fail!(Error::<T, I>::InvalidUnrewardedRelayers);
},
};
let confirmed_messages = lane
.confirm_delivery(
relayers_state.total_messages,
last_delivered_nonce,
&lane_data.relayers,
)
.map_err(Error::<T, I>::ReceivalConfirmation)?;
if let Some(confirmed_messages) = confirmed_messages {
// emit 'delivered' event
@@ -554,12 +518,12 @@ pub mod pallet {
NotOperatingNormally,
/// The outbound lane is inactive.
InactiveOutboundLane,
/// The message is too large to be sent over the bridge.
MessageIsTooLarge,
/// Message has been treated as invalid by chain verifier.
MessageRejectedByChainVerifier,
MessageRejectedByChainVerifier(VerificationError),
/// Message has been treated as invalid by lane verifier.
MessageRejectedByLaneVerifier,
MessageRejectedByLaneVerifier(VerificationError),
/// Message has been treated as invalid by the pallet logic.
MessageRejectedByPallet(VerificationError),
/// Submitter has failed to pay fee for delivering and dispatching messages.
FailedToWithdrawMessageFee,
/// The transaction brings too many messages.
@@ -568,8 +532,6 @@ pub mod pallet {
InvalidMessagesProof,
/// Invalid messages delivery proof has been submitted.
InvalidMessagesDeliveryProof,
/// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane).
InvalidUnrewardedRelayers,
/// The relayer has declared invalid unrewarded relayers state in the
/// `receive_messages_delivery_proof` call.
InvalidUnrewardedRelayersState,
@@ -578,9 +540,8 @@ pub mod pallet {
InsufficientDispatchWeight,
/// The message someone is trying to work with (i.e. increase fee) is not yet sent.
MessageIsNotYetSent,
/// The number of actually confirmed messages is going to be larger than the number of
/// messages in the proof. This may mean that this or bridged chain storage is corrupted.
TryingToConfirmMoreMessagesThanExpected,
/// Error confirming messages receival.
ReceivalConfirmation(ReceivalConfirmationError),
/// Error generated by the `OwnedBridgeModule` trait.
BridgeModule(bp_runtime::OwnedBridgeModuleError),
}
@@ -732,7 +693,7 @@ fn send_message<T: Config<I>, I: 'static>(
err,
);
Error::<T, I>::MessageRejectedByChainVerifier
Error::<T, I>::MessageRejectedByChainVerifier(err)
})?;
// now let's enforce any additional lane rules
@@ -746,18 +707,16 @@ fn send_message<T: Config<I>, I: 'static>(
err,
);
Error::<T, I>::MessageRejectedByLaneVerifier
Error::<T, I>::MessageRejectedByLaneVerifier(err)
},
)?;
// finally, save message in outbound storage and emit event
let encoded_payload = payload.encode();
let encoded_payload_len = encoded_payload.len();
ensure!(
encoded_payload_len <= T::MaximalOutboundPayloadSize::get() as usize,
Error::<T, I>::MessageIsTooLarge
);
let nonce = lane.send_message(encoded_payload);
let nonce = lane
.send_message(encoded_payload)
.map_err(Error::<T, I>::MessageRejectedByPallet)?;
log::trace!(
target: LOG_TARGET,
@@ -787,18 +746,7 @@ fn ensure_normal_operating_mode<T: Config<I>, I: 'static>() -> Result<(), Error<
fn inbound_lane<T: Config<I>, I: 'static>(
lane_id: LaneId,
) -> InboundLane<RuntimeInboundLaneStorage<T, I>> {
InboundLane::new(inbound_lane_storage::<T, I>(lane_id))
}
/// Creates new runtime inbound lane storage.
fn inbound_lane_storage<T: Config<I>, I: 'static>(
lane_id: LaneId,
) -> RuntimeInboundLaneStorage<T, I> {
RuntimeInboundLaneStorage {
lane_id,
cached_data: RefCell::new(None),
_phantom: Default::default(),
}
InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id))
}
/// Creates new outbound lane object, backed by runtime storage.
@@ -811,10 +759,17 @@ fn outbound_lane<T: Config<I>, I: 'static>(
/// Runtime inbound lane storage.
struct RuntimeInboundLaneStorage<T: Config<I>, I: 'static = ()> {
lane_id: LaneId,
cached_data: RefCell<Option<InboundLaneData<T::InboundRelayer>>>,
cached_data: Option<InboundLaneData<T::InboundRelayer>>,
_phantom: PhantomData<I>,
}
impl<T: Config<I>, I: 'static> RuntimeInboundLaneStorage<T, I> {
/// Creates new runtime inbound lane storage.
fn from_lane_id(lane_id: LaneId) -> RuntimeInboundLaneStorage<T, I> {
RuntimeInboundLaneStorage { lane_id, cached_data: None, _phantom: Default::default() }
}
}
impl<T: Config<I>, I: 'static> RuntimeInboundLaneStorage<T, I> {
/// Returns number of bytes that may be subtracted from the PoV component of
/// `receive_messages_proof` call, because the actual inbound lane state is smaller than the
@@ -824,9 +779,9 @@ impl<T: Config<I>, I: 'static> RuntimeInboundLaneStorage<T, I> {
/// `MaxUnrewardedRelayerEntriesAtInboundLane` constant from the pallet configuration. The PoV
/// of the call includes the maximal size of inbound lane state. If the actual size is smaller,
/// we may subtract extra bytes from this component.
pub fn extra_proof_size_bytes(&self) -> u64 {
pub fn extra_proof_size_bytes(&mut self) -> u64 {
let max_encoded_len = StoredInboundLaneData::<T, I>::max_encoded_len();
let relayers_count = self.data().relayers.len();
let relayers_count = self.get_or_init_data().relayers.len();
let actual_encoded_len =
InboundLaneData::<T::InboundRelayer>::encoded_size_hint(relayers_count)
.unwrap_or(usize::MAX);
@@ -849,26 +804,20 @@ impl<T: Config<I>, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage<
T::MaxUnconfirmedMessagesAtInboundLane::get()
}
fn data(&self) -> InboundLaneData<T::InboundRelayer> {
match self.cached_data.clone().into_inner() {
Some(data) => data,
fn get_or_init_data(&mut self) -> InboundLaneData<T::InboundRelayer> {
match self.cached_data {
Some(ref data) => data.clone(),
None => {
let data: InboundLaneData<T::InboundRelayer> =
InboundLanes::<T, I>::get(self.lane_id).into();
*self.cached_data.try_borrow_mut().expect(
"we're in the single-threaded environment;\
we have no recursive borrows; qed",
) = Some(data.clone());
self.cached_data = Some(data.clone());
data
},
}
}
fn set_data(&mut self, data: InboundLaneData<T::InboundRelayer>) {
*self.cached_data.try_borrow_mut().expect(
"we're in the single-threaded environment;\
we have no recursive borrows; qed",
) = Some(data.clone());
self.cached_data = Some(data.clone());
InboundLanes::<T, I>::insert(self.lane_id, StoredInboundLaneData::<T, I>(data))
}
}
@@ -898,15 +847,17 @@ impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag
.map(Into::into)
}
fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload) {
fn save_message(
&mut self,
nonce: MessageNonce,
message_payload: MessagePayload,
) -> Result<(), VerificationError> {
OutboundMessages::<T, I>::insert(
MessageKey { lane_id: self.lane_id, nonce },
StoredMessagePayload::<T, I>::try_from(message_payload).expect(
"save_message is called after all checks in send_message; \
send_message checks message size; \
qed",
),
StoredMessagePayload::<T, I>::try_from(message_payload)
.map_err(|_| VerificationError::MessageTooLarge)?,
);
Ok(())
}
fn remove_message(&mut self, nonce: &MessageNonce) {
@@ -918,7 +869,7 @@ impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag
fn verify_and_decode_messages_proof<Chain: SourceHeaderChain, DispatchPayload: Decode>(
proof: Chain::MessagesProof,
messages_count: u32,
) -> Result<ProvedMessages<DispatchMessage<DispatchPayload>>, Chain::Error> {
) -> Result<ProvedMessages<DispatchMessage<DispatchPayload>>, VerificationError> {
// `receive_messages_proof` weight formula and `MaxUnconfirmedMessagesAtInboundLane` check
// guarantees that the `message_count` is sane and Vec<Message> may be allocated.
// (tx with too many messages will either be rejected from the pool, or will fail earlier)
@@ -941,13 +892,16 @@ fn verify_and_decode_messages_proof<Chain: SourceHeaderChain, DispatchPayload: D
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{
inbound_unrewarded_relayers_state, message, message_payload, run_test, unrewarded_relayer,
AccountId, DbWeight, RuntimeEvent as TestEvent, RuntimeOrigin,
TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessagesDeliveryProof,
TestMessagesProof, TestRelayer, TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE,
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2,
TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B,
use crate::{
mock::{
inbound_unrewarded_relayers_state, message, message_payload, run_test,
unrewarded_relayer, AccountId, DbWeight, RuntimeEvent as TestEvent, RuntimeOrigin,
TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessagesDeliveryProof,
TestMessagesProof, TestRelayer, TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE,
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2,
TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B,
},
outbound_lane::ReceivalConfirmationError,
};
use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState};
use bp_test_utils::generate_owned_bridge_module_tests;
@@ -1008,9 +962,9 @@ mod tests {
))),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
messages_in_oldest_entry: 1,
total_messages: 1,
last_delivered_nonce: 1,
..Default::default()
},
));
@@ -1151,7 +1105,9 @@ mod tests {
TEST_LANE_ID,
message_payload.clone(),
),
Error::<TestRuntime, ()>::MessageIsTooLarge,
Error::<TestRuntime, ()>::MessageRejectedByPallet(
VerificationError::MessageTooLarge
),
);
// let's check that we're able to send `MAX_OUTBOUND_PAYLOAD_SIZE` messages
@@ -1177,7 +1133,9 @@ mod tests {
TEST_LANE_ID,
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
),
Error::<TestRuntime, ()>::MessageRejectedByChainVerifier,
Error::<TestRuntime, ()>::MessageRejectedByChainVerifier(VerificationError::Other(
mock::TEST_ERROR
)),
);
});
}
@@ -1190,7 +1148,9 @@ mod tests {
message.reject_by_lane_verifier = true;
assert_noop!(
send_message::<TestRuntime, ()>(RuntimeOrigin::signed(1), TEST_LANE_ID, message,),
Error::<TestRuntime, ()>::MessageRejectedByLaneVerifier,
Error::<TestRuntime, ()>::MessageRejectedByLaneVerifier(VerificationError::Other(
mock::TEST_ERROR
)),
);
});
}
@@ -1368,9 +1328,9 @@ mod tests {
single_message_delivery_proof,
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
messages_in_oldest_entry: 1,
total_messages: 1,
last_delivered_nonce: 1,
..Default::default()
},
);
assert_ok!(result);
@@ -1408,9 +1368,9 @@ mod tests {
two_messages_delivery_proof,
UnrewardedRelayersState {
unrewarded_relayer_entries: 2,
messages_in_oldest_entry: 1,
total_messages: 2,
last_delivered_nonce: 2,
..Default::default()
},
);
assert_ok!(result);
@@ -1773,9 +1733,9 @@ mod tests {
TestMessagesDeliveryProof(messages_1_and_2_proof),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
messages_in_oldest_entry: 2,
total_messages: 2,
last_delivered_nonce: 2,
..Default::default()
},
));
// second tx with message 3
@@ -1784,9 +1744,9 @@ mod tests {
TestMessagesDeliveryProof(messages_3_proof),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
messages_in_oldest_entry: 1,
total_messages: 1,
last_delivered_nonce: 3,
..Default::default()
},
));
});
@@ -1814,7 +1774,9 @@ mod tests {
))),
UnrewardedRelayersState { last_delivered_nonce: 1, ..Default::default() },
),
Error::<TestRuntime, ()>::TryingToConfirmMoreMessagesThanExpected,
Error::<TestRuntime, ()>::ReceivalConfirmation(
ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected
),
);
});
}
@@ -2114,10 +2076,10 @@ mod tests {
fn storage(relayer_entries: usize) -> RuntimeInboundLaneStorage<TestRuntime, ()> {
RuntimeInboundLaneStorage {
lane_id: Default::default(),
cached_data: RefCell::new(Some(InboundLaneData {
cached_data: Some(InboundLaneData {
relayers: vec![relayer_entry(); relayer_entries].into_iter().collect(),
last_confirmed_nonce: 0,
})),
}),
_phantom: Default::default(),
}
}
+12 -15
View File
@@ -27,7 +27,7 @@ use bp_messages::{
ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
},
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload,
OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState,
OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, VerificationError,
};
use bp_runtime::{messages::MessageDispatchResult, Size};
use codec::{Decode, Encode};
@@ -295,13 +295,11 @@ impl Size for TestMessagesDeliveryProof {
pub struct TestTargetHeaderChain;
impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
type Error = &'static str;
type MessagesDeliveryProof = TestMessagesDeliveryProof;
fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> {
fn verify_message(payload: &TestPayload) -> Result<(), VerificationError> {
if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN {
Err(TEST_ERROR)
Err(VerificationError::Other(TEST_ERROR))
} else {
Ok(())
}
@@ -309,8 +307,8 @@ impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<TestRelayer>), Self::Error> {
proof.0.map_err(|_| TEST_ERROR)
) -> Result<(LaneId, InboundLaneData<TestRelayer>), VerificationError> {
proof.0.map_err(|_| VerificationError::Other(TEST_ERROR))
}
}
@@ -319,18 +317,16 @@ impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
pub struct TestLaneMessageVerifier;
impl LaneMessageVerifier<RuntimeOrigin, TestPayload> for TestLaneMessageVerifier {
type Error = &'static str;
fn verify_message(
_submitter: &RuntimeOrigin,
_lane: &LaneId,
_lane_outbound_data: &OutboundLaneData,
payload: &TestPayload,
) -> Result<(), Self::Error> {
) -> Result<(), VerificationError> {
if !payload.reject_by_lane_verifier {
Ok(())
} else {
Err(TEST_ERROR)
Err(VerificationError::Other(TEST_ERROR))
}
}
}
@@ -400,15 +396,16 @@ impl DeliveryConfirmationPayments<AccountId> for TestDeliveryConfirmationPayment
pub struct TestSourceHeaderChain;
impl SourceHeaderChain for TestSourceHeaderChain {
type Error = &'static str;
type MessagesProof = TestMessagesProof;
fn verify_messages_proof(
proof: Self::MessagesProof,
_messages_count: u32,
) -> Result<ProvedMessages<Message>, Self::Error> {
proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR)
) -> Result<ProvedMessages<Message>, VerificationError> {
proof
.result
.map(|proof| proof.into_iter().collect())
.map_err(|_| VerificationError::Other(TEST_ERROR))
}
}
@@ -16,16 +16,19 @@
//! Everything about outgoing messages sending.
use crate::Config;
use crate::{Config, LOG_TARGET};
use bp_messages::{
DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer,
VerificationError,
};
use codec::{Decode, Encode};
use frame_support::{
weights::{RuntimeDbWeight, Weight},
BoundedVec, RuntimeDebug,
BoundedVec, PalletError, RuntimeDebug,
};
use num_traits::Zero;
use scale_info::TypeInfo;
use sp_std::collections::vec_deque::VecDeque;
/// Outbound lane storage.
@@ -40,7 +43,11 @@ pub trait OutboundLaneStorage {
#[cfg(test)]
fn message(&self, nonce: &MessageNonce) -> Option<MessagePayload>;
/// Save outbound message in the storage.
fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload);
fn save_message(
&mut self,
nonce: MessageNonce,
message_payload: MessagePayload,
) -> Result<(), VerificationError>;
/// Remove outbound message from the storage.
fn remove_message(&mut self, nonce: &MessageNonce);
}
@@ -49,13 +56,8 @@ pub trait OutboundLaneStorage {
pub type StoredMessagePayload<T, I> = BoundedVec<u8, <T as Config<I>>::MaximalOutboundPayloadSize>;
/// Result of messages receival confirmation.
#[derive(RuntimeDebug, PartialEq, Eq)]
pub enum ReceivalConfirmationResult {
/// New messages have been confirmed by the confirmation transaction.
ConfirmedMessages(DeliveredMessages),
/// Confirmation transaction brings no new confirmation. This may be a result of relayer
/// error or several relayers running.
NoNewConfirmations,
#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
pub enum ReceivalConfirmationError {
/// Bridged chain is trying to confirm more messages than we have generated. May be a result
/// of invalid bridged chain storage.
FailedToConfirmFutureMessages,
@@ -66,7 +68,7 @@ pub enum ReceivalConfirmationResult {
/// bridged chain storage.
NonConsecutiveUnrewardedRelayerEntries,
/// The chain has more messages that need to be confirmed than there is in the proof.
TryingToConfirmMoreMessagesThanExpected(MessageNonce),
TryingToConfirmMoreMessagesThanExpected,
}
/// Outbound messages lane.
@@ -88,15 +90,18 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
/// Send message over lane.
///
/// Returns new message nonce.
pub fn send_message(&mut self, message_payload: MessagePayload) -> MessageNonce {
pub fn send_message(
&mut self,
message_payload: MessagePayload,
) -> Result<MessageNonce, VerificationError> {
let mut data = self.storage.data();
let nonce = data.latest_generated_nonce + 1;
data.latest_generated_nonce = nonce;
self.storage.save_message(nonce, message_payload);
self.storage.save_message(nonce, message_payload)?;
self.storage.set_data(data);
nonce
Ok(nonce)
}
/// Confirm messages delivery.
@@ -105,37 +110,39 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
max_allowed_messages: MessageNonce,
latest_delivered_nonce: MessageNonce,
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
) -> ReceivalConfirmationResult {
) -> Result<Option<DeliveredMessages>, ReceivalConfirmationError> {
let mut data = self.storage.data();
if latest_delivered_nonce <= data.latest_received_nonce {
return ReceivalConfirmationResult::NoNewConfirmations
let confirmed_messages = DeliveredMessages {
begin: data.latest_received_nonce.saturating_add(1),
end: latest_delivered_nonce,
};
if confirmed_messages.total_messages() == 0 {
return Ok(None)
}
if latest_delivered_nonce > data.latest_generated_nonce {
return ReceivalConfirmationResult::FailedToConfirmFutureMessages
if confirmed_messages.end > data.latest_generated_nonce {
return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages)
}
if latest_delivered_nonce - data.latest_received_nonce > max_allowed_messages {
if confirmed_messages.total_messages() > max_allowed_messages {
// that the relayer has declared correct number of messages that the proof contains (it
// is checked outside of the function). But it may happen (but only if this/bridged
// chain storage is corrupted, though) that the actual number of confirmed messages if
// larger than declared. This would mean that 'reward loop' will take more time than the
// weight formula accounts, so we can't allow that.
return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(
latest_delivered_nonce - data.latest_received_nonce,
)
log::trace!(
target: LOG_TARGET,
"Messages delivery proof contains too many messages to confirm: {} vs declared {}",
confirmed_messages.total_messages(),
max_allowed_messages,
);
return Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected)
}
if let Err(e) = ensure_unrewarded_relayers_are_correct(latest_delivered_nonce, relayers) {
return e
}
ensure_unrewarded_relayers_are_correct(confirmed_messages.end, relayers)?;
let prev_latest_received_nonce = data.latest_received_nonce;
data.latest_received_nonce = latest_delivered_nonce;
data.latest_received_nonce = confirmed_messages.end;
self.storage.set_data(data);
ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages {
begin: prev_latest_received_nonce + 1,
end: latest_delivered_nonce,
})
Ok(Some(confirmed_messages))
}
/// Prune at most `max_messages_to_prune` already received messages.
@@ -176,27 +183,24 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
fn ensure_unrewarded_relayers_are_correct<RelayerId>(
latest_received_nonce: MessageNonce,
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
) -> Result<(), ReceivalConfirmationResult> {
let mut last_entry_end: Option<MessageNonce> = None;
) -> Result<(), ReceivalConfirmationError> {
let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin);
for entry in relayers {
// unrewarded relayer entry must have at least 1 unconfirmed message
// (guaranteed by the `InboundLane::receive_message()`)
if entry.messages.end < entry.messages.begin {
return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry)
return Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry)
}
// every entry must confirm range of messages that follows previous entry range
// (guaranteed by the `InboundLane::receive_message()`)
if let Some(last_entry_end) = last_entry_end {
let expected_entry_begin = last_entry_end.checked_add(1);
if expected_entry_begin != Some(entry.messages.begin) {
return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries)
}
if expected_entry_begin != Some(entry.messages.begin) {
return Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries)
}
last_entry_end = Some(entry.messages.end);
expected_entry_begin = entry.messages.end.checked_add(1);
// entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()`
// (guaranteed by the `InboundLane::receive_message()`)
if entry.messages.end > latest_received_nonce {
return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages)
return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages)
}
}
@@ -213,7 +217,7 @@ mod tests {
},
outbound_lane,
};
use frame_support::weights::constants::RocksDbWeight;
use frame_support::{assert_ok, weights::constants::RocksDbWeight};
use sp_std::ops::RangeInclusive;
fn unrewarded_relayers(
@@ -231,12 +235,12 @@ mod tests {
fn assert_3_messages_confirmation_fails(
latest_received_nonce: MessageNonce,
relayers: &VecDeque<UnrewardedRelayer<TestRelayer>>,
) -> ReceivalConfirmationResult {
) -> Result<Option<DeliveredMessages>, ReceivalConfirmationError> {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
let result = lane.confirm_delivery(3, latest_received_nonce, relayers);
@@ -251,7 +255,7 @@ mod tests {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert_eq!(lane.storage.data().latest_generated_nonce, 0);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1));
assert!(lane.storage.message(&1).is_some());
assert_eq!(lane.storage.data().latest_generated_nonce, 1);
});
@@ -261,14 +265,14 @@ mod tests {
fn confirm_delivery_works() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1));
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(2));
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(3));
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
Ok(Some(delivered_messages(1..=3))),
);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 3);
@@ -279,26 +283,20 @@ mod tests {
fn confirm_delivery_rejects_nonce_lesser_than_latest_received() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
);
assert_eq!(
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::NoNewConfirmations,
Ok(Some(delivered_messages(1..=3))),
);
assert_eq!(lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), Ok(None),);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 3);
assert_eq!(
lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)),
ReceivalConfirmationResult::NoNewConfirmations,
);
assert_eq!(lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)), Ok(None),);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 3);
});
@@ -308,7 +306,7 @@ mod tests {
fn confirm_delivery_rejects_nonce_larger_than_last_generated() {
assert_eq!(
assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),),
ReceivalConfirmationResult::FailedToConfirmFutureMessages,
Err(ReceivalConfirmationError::FailedToConfirmFutureMessages),
);
}
@@ -323,7 +321,7 @@ mod tests {
.chain(unrewarded_relayers(3..=3).into_iter())
.collect(),
),
ReceivalConfirmationResult::FailedToConfirmFutureMessages,
Err(ReceivalConfirmationError::FailedToConfirmFutureMessages),
);
}
@@ -339,7 +337,7 @@ mod tests {
.chain(unrewarded_relayers(2..=3).into_iter())
.collect(),
),
ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry,
Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry),
);
}
@@ -354,7 +352,7 @@ mod tests {
.chain(unrewarded_relayers(2..=2).into_iter())
.collect(),
),
ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries,
Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries),
);
}
@@ -369,9 +367,9 @@ mod tests {
);
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
// when nothing is confirmed, nothing is pruned
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert!(lane.storage.message(&1).is_some());
assert!(lane.storage.message(&2).is_some());
assert!(lane.storage.message(&3).is_some());
@@ -383,7 +381,7 @@ mod tests {
// after confirmation, some messages are received
assert_eq!(
lane.confirm_delivery(2, 2, &unrewarded_relayers(1..=2)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)),
Ok(Some(delivered_messages(1..=2))),
);
assert_eq!(
lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)),
@@ -396,7 +394,7 @@ mod tests {
// after last message is confirmed, everything is pruned
assert_eq!(
lane.confirm_delivery(1, 3, &unrewarded_relayers(3..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)),
Ok(Some(delivered_messages(3..=3))),
);
assert_eq!(
lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)),
@@ -413,20 +411,20 @@ mod tests {
fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)));
assert_eq!(
lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3),
Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected),
);
assert_eq!(
lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3),
Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected),
);
assert_eq!(
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
Ok(Some(delivered_messages(1..=3))),
);
});
}