mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-16 17:45:44 +00:00
Bridges subtree sync (#3022)
* Squashed 'bridges/' changes from edf33a2c85..277f0d5496 277f0d5496 Dynamic fees for bridges-v1 (#2294) b1c51f7dd2 Finality loop refactoring (#2357) 620db2b10f Add equivocation detector crate and implement clients (#2348) (#2353) 3fe4b13eb4 Add basic equivocation detection pipeline schema (#2338) (#2341) git-subtree-dir: bridges git-subtree-split: 277f0d54961c800b231d8123c6445f378b1deb89 * [dynfees] Rococo/Wococo does not need congestion and dynamic fees (for now) * Fix * ".git/.scripts/commands/fmt/fmt.sh" * Forgotten bridges/Cargo.lock --------- Co-authored-by: command-bot <>
This commit is contained in:
@@ -53,7 +53,8 @@ use crate::{
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::{
|
||||
DeliveryConfirmationPayments, LaneMessageVerifier, SendMessageArtifacts, TargetHeaderChain,
|
||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered,
|
||||
SendMessageArtifacts, TargetHeaderChain,
|
||||
},
|
||||
target_chain::{
|
||||
DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages,
|
||||
@@ -63,7 +64,9 @@ use bp_messages::{
|
||||
MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails,
|
||||
UnrewardedRelayersState, VerificationError,
|
||||
};
|
||||
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size};
|
||||
use bp_runtime::{
|
||||
BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, RangeInclusiveExt, Size,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get, DefaultNoBound};
|
||||
use sp_runtime::traits::UniqueSaturatedFrom;
|
||||
@@ -156,6 +159,8 @@ pub mod pallet {
|
||||
type LaneMessageVerifier: LaneMessageVerifier<Self::OutboundPayload>;
|
||||
/// Delivery confirmation payments.
|
||||
type DeliveryConfirmationPayments: DeliveryConfirmationPayments<Self::AccountId>;
|
||||
/// Delivery confirmation callback.
|
||||
type OnMessagesDelivered: OnMessagesDelivered;
|
||||
|
||||
// Types that are used by inbound_lane (on target chain).
|
||||
|
||||
@@ -281,6 +286,9 @@ pub mod pallet {
|
||||
Error::<T, I>::TooManyMessagesInTheProof
|
||||
);
|
||||
|
||||
// if message dispatcher is currently inactive, we won't accept any messages
|
||||
ensure!(T::MessageDispatch::is_active(), Error::<T, I>::MessageDispatchInactive);
|
||||
|
||||
// why do we need to know the weight of this (`receive_messages_proof`) call? Because
|
||||
// we may want to return some funds for not-dispatching (or partially dispatching) some
|
||||
// messages to the call origin (relayer). And this is done by returning actual weight
|
||||
@@ -487,6 +495,12 @@ pub mod pallet {
|
||||
lane_id,
|
||||
);
|
||||
|
||||
// notify others about messages delivery
|
||||
T::OnMessagesDelivered::on_messages_delivered(
|
||||
lane_id,
|
||||
lane.data().queued_messages().saturating_len(),
|
||||
);
|
||||
|
||||
// because of lags, the inbound lane state (`lane_data`) may have entries for
|
||||
// already rewarded relayers and messages (if all entries are duplicated, then
|
||||
// this transaction must be filtered out by our signed extension)
|
||||
@@ -518,6 +532,8 @@ pub mod pallet {
|
||||
NotOperatingNormally,
|
||||
/// The outbound lane is inactive.
|
||||
InactiveOutboundLane,
|
||||
/// The inbound message dispatcher is inactive.
|
||||
MessageDispatchInactive,
|
||||
/// Message has been treated as invalid by chain verifier.
|
||||
MessageRejectedByChainVerifier(VerificationError),
|
||||
/// Message has been treated as invalid by lane verifier.
|
||||
@@ -580,6 +596,25 @@ pub mod pallet {
|
||||
MaxValues = MaybeOutboundLanesCount<T, I>,
|
||||
>;
|
||||
|
||||
/// Map of lane id => is congested signal sent. It is managed by the
|
||||
/// `bridge_runtime_common::LocalXcmQueueManager`.
|
||||
///
|
||||
/// **bridges-v1**: this map is a temporary hack and will be dropped in the `v2`. We can emulate
|
||||
/// a storage map using `sp_io::unhashed` storage functions, but then benchmarks are not
|
||||
/// accounting its `proof_size`, so it is missing from the final weights. So we need to make it
|
||||
/// a map inside some pallet. We could use a simply value instead of map here, because
|
||||
/// in `v1` we'll only have a single lane. But in the case of adding another lane before `v2`,
|
||||
/// it'll be easier to deal with the isolated storage map instead.
|
||||
#[pallet::storage]
|
||||
pub type OutboundLanesCongestedSignals<T: Config<I>, I: 'static = ()> = StorageMap<
|
||||
Hasher = Blake2_128Concat,
|
||||
Key = LaneId,
|
||||
Value = bool,
|
||||
QueryKind = ValueQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = MaybeOutboundLanesCount<T, I>,
|
||||
>;
|
||||
|
||||
/// All queued outbound messages.
|
||||
#[pallet::storage]
|
||||
pub type OutboundMessages<T: Config<I>, I: 'static = ()> =
|
||||
@@ -627,6 +662,11 @@ pub mod pallet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return outbound lane data.
|
||||
pub fn outbound_lane_data(lane: LaneId) -> OutboundLaneData {
|
||||
OutboundLanes::<T, I>::get(lane)
|
||||
}
|
||||
|
||||
/// Return inbound lane data.
|
||||
pub fn inbound_lane_data(lane: LaneId) -> InboundLaneData<T::InboundRelayer> {
|
||||
InboundLanes::<T, I>::get(lane).0
|
||||
@@ -703,6 +743,9 @@ fn send_message<T: Config<I>, I: 'static>(
|
||||
.send_message(encoded_payload)
|
||||
.map_err(Error::<T, I>::MessageRejectedByPallet)?;
|
||||
|
||||
// return number of messages in the queue to let sender know about its state
|
||||
let enqueued_messages = lane.data().queued_messages().saturating_len();
|
||||
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"Accepted message {} to lane {:?}. Message size: {:?}",
|
||||
@@ -713,7 +756,7 @@ fn send_message<T: Config<I>, I: 'static>(
|
||||
|
||||
Pallet::<T, I>::deposit_event(Event::MessageAccepted { lane_id, nonce });
|
||||
|
||||
Ok(SendMessageArtifacts { nonce })
|
||||
Ok(SendMessageArtifacts { nonce, enqueued_messages })
|
||||
}
|
||||
|
||||
/// Ensure that the pallet is in normal operational mode.
|
||||
@@ -881,8 +924,9 @@ mod tests {
|
||||
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,
|
||||
TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessageDispatch,
|
||||
TestMessagesDeliveryProof, TestMessagesProof, TestOnMessagesDelivered, 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,
|
||||
},
|
||||
@@ -908,10 +952,12 @@ mod tests {
|
||||
fn send_regular_message() {
|
||||
get_ready_for_events();
|
||||
|
||||
let message_nonce =
|
||||
outbound_lane::<TestRuntime, ()>(TEST_LANE_ID).data().latest_generated_nonce + 1;
|
||||
send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD)
|
||||
let outbound_lane = outbound_lane::<TestRuntime, ()>(TEST_LANE_ID);
|
||||
let message_nonce = outbound_lane.data().latest_generated_nonce + 1;
|
||||
let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len();
|
||||
let artifacts = send_message::<TestRuntime, ()>(TEST_LANE_ID, REGULAR_PAYLOAD)
|
||||
.expect("send_message has failed");
|
||||
assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1);
|
||||
|
||||
// check event with assigned nonce
|
||||
assert_eq!(
|
||||
@@ -1201,6 +1247,23 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn receive_messages_fails_if_dispatcher_is_inactive() {
|
||||
run_test(|| {
|
||||
TestMessageDispatch::deactivate();
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::receive_messages_proof(
|
||||
RuntimeOrigin::signed(1),
|
||||
TEST_RELAYER_A,
|
||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||
1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
),
|
||||
Error::<TestRuntime, ()>::MessageDispatchInactive,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn receive_messages_proof_does_not_accept_message_if_dispatch_weight_is_not_enough() {
|
||||
run_test(|| {
|
||||
@@ -1304,6 +1367,7 @@ mod tests {
|
||||
);
|
||||
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
||||
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
||||
assert_eq!(TestOnMessagesDelivered::call_arguments(), Some((TEST_LANE_ID, 1)));
|
||||
|
||||
// this reports delivery of both message 1 and message 2 => reward is paid only to
|
||||
// TEST_RELAYER_B
|
||||
@@ -1346,6 +1410,7 @@ mod tests {
|
||||
);
|
||||
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
||||
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
||||
assert_eq!(TestOnMessagesDelivered::call_arguments(), Some((TEST_LANE_ID, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ use crate::Config;
|
||||
|
||||
use bp_messages::{
|
||||
calc_relayers_rewards,
|
||||
source_chain::{DeliveryConfirmationPayments, LaneMessageVerifier, TargetHeaderChain},
|
||||
source_chain::{
|
||||
DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, TargetHeaderChain,
|
||||
},
|
||||
target_chain::{
|
||||
DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch,
|
||||
ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
|
||||
@@ -161,6 +163,7 @@ impl Config for TestRuntime {
|
||||
type TargetHeaderChain = TestTargetHeaderChain;
|
||||
type LaneMessageVerifier = TestLaneMessageVerifier;
|
||||
type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments;
|
||||
type OnMessagesDelivered = TestOnMessagesDelivered;
|
||||
|
||||
type SourceHeaderChain = TestSourceHeaderChain;
|
||||
type MessageDispatch = TestMessageDispatch;
|
||||
@@ -402,14 +405,26 @@ impl SourceHeaderChain for TestSourceHeaderChain {
|
||||
}
|
||||
}
|
||||
|
||||
/// Source header chain that is used in tests.
|
||||
/// Test message dispatcher.
|
||||
#[derive(Debug)]
|
||||
pub struct TestMessageDispatch;
|
||||
|
||||
impl TestMessageDispatch {
|
||||
pub fn deactivate() {
|
||||
frame_support::storage::unhashed::put(b"TestMessageDispatch.IsCongested", &true)
|
||||
}
|
||||
}
|
||||
|
||||
impl MessageDispatch for TestMessageDispatch {
|
||||
type DispatchPayload = TestPayload;
|
||||
type DispatchLevelResult = TestDispatchLevelResult;
|
||||
|
||||
fn is_active() -> bool {
|
||||
!frame_support::storage::unhashed::get_or_default::<bool>(
|
||||
b"TestMessageDispatch.IsCongested",
|
||||
)
|
||||
}
|
||||
|
||||
fn dispatch_weight(message: &mut DispatchMessage<TestPayload>) -> Weight {
|
||||
match message.data.payload.as_ref() {
|
||||
Ok(payload) => payload.declared_weight,
|
||||
@@ -427,6 +442,24 @@ impl MessageDispatch for TestMessageDispatch {
|
||||
}
|
||||
}
|
||||
|
||||
/// Test callback, called during message delivery confirmation transaction.
|
||||
pub struct TestOnMessagesDelivered;
|
||||
|
||||
impl TestOnMessagesDelivered {
|
||||
pub fn call_arguments() -> Option<(LaneId, MessageNonce)> {
|
||||
frame_support::storage::unhashed::get(b"TestOnMessagesDelivered.OnMessagesDelivered")
|
||||
}
|
||||
}
|
||||
|
||||
impl OnMessagesDelivered for TestOnMessagesDelivered {
|
||||
fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) {
|
||||
frame_support::storage::unhashed::put(
|
||||
b"TestOnMessagesDelivered.OnMessagesDelivered",
|
||||
&(lane, enqueued_messages),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return test lane message with given nonce and payload.
|
||||
pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message {
|
||||
Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, payload: payload.encode() }
|
||||
|
||||
Reference in New Issue
Block a user