mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 05:11:02 +00:00
refund extra weight in receive_messages_delivery_proof call (#2031)
This commit is contained in:
committed by
Bastian Köcher
parent
f7380490c0
commit
9e48162df2
@@ -63,7 +63,7 @@ use bp_messages::{
|
|||||||
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
|
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
|
||||||
OutboundMessageDetails, UnrewardedRelayersState,
|
OutboundMessageDetails, UnrewardedRelayersState,
|
||||||
};
|
};
|
||||||
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size};
|
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size};
|
||||||
use codec::{Decode, Encode, MaxEncodedLen};
|
use codec::{Decode, Encode, MaxEncodedLen};
|
||||||
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get};
|
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get};
|
||||||
use sp_runtime::{traits::UniqueSaturatedFrom, SaturatedConversion};
|
use sp_runtime::{traits::UniqueSaturatedFrom, SaturatedConversion};
|
||||||
@@ -423,10 +423,11 @@ pub mod pallet {
|
|||||||
pub fn receive_messages_delivery_proof(
|
pub fn receive_messages_delivery_proof(
|
||||||
origin: OriginFor<T>,
|
origin: OriginFor<T>,
|
||||||
proof: MessagesDeliveryProofOf<T, I>,
|
proof: MessagesDeliveryProofOf<T, I>,
|
||||||
relayers_state: UnrewardedRelayersState,
|
mut relayers_state: UnrewardedRelayersState,
|
||||||
) -> DispatchResult {
|
) -> DispatchResultWithPostInfo {
|
||||||
Self::ensure_not_halted().map_err(Error::<T, I>::BridgeModule)?;
|
Self::ensure_not_halted().map_err(Error::<T, I>::BridgeModule)?;
|
||||||
|
|
||||||
|
let proof_size = proof.size();
|
||||||
let confirmation_relayer = ensure_signed(origin)?;
|
let confirmation_relayer = ensure_signed(origin)?;
|
||||||
let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof)
|
let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
@@ -499,13 +500,27 @@ pub mod pallet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// if some new messages have been confirmed, reward relayers
|
// if some new messages have been confirmed, reward relayers
|
||||||
T::DeliveryConfirmationPayments::pay_reward(
|
let actually_rewarded_relayers = T::DeliveryConfirmationPayments::pay_reward(
|
||||||
lane_id,
|
lane_id,
|
||||||
lane_data.relayers,
|
lane_data.relayers,
|
||||||
&confirmation_relayer,
|
&confirmation_relayer,
|
||||||
&received_range,
|
&received_range,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
// update relayers state with actual numbers to compute actual weight below
|
||||||
|
relayers_state.unrewarded_relayer_entries = sp_std::cmp::min(
|
||||||
|
relayers_state.unrewarded_relayer_entries,
|
||||||
|
actually_rewarded_relayers,
|
||||||
|
);
|
||||||
|
relayers_state.total_messages = sp_std::cmp::min(
|
||||||
|
relayers_state.total_messages,
|
||||||
|
received_range
|
||||||
|
.end()
|
||||||
|
.checked_sub(*received_range.start())
|
||||||
|
.and_then(|x| x.checked_add(1))
|
||||||
|
.unwrap_or(MessageNonce::MAX),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
@@ -514,11 +529,15 @@ pub mod pallet {
|
|||||||
lane_id,
|
lane_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: https://github.com/paritytech/parity-bridges-common/issues/2020
|
// because of lags, the inbound lane state (`lane_data`) may have entries for
|
||||||
// we need to refund unused weight (because the inbound lane state may contain
|
// already rewarded relayers and messages (if all entries are duplicated, then
|
||||||
// already confirmed messages and already rewarded relayer entries)
|
// this transaction must be filtered out by our signed extension)
|
||||||
|
let actual_weight = T::WeightInfo::receive_messages_delivery_proof_weight(
|
||||||
|
&PreComputedSize(proof_size as usize),
|
||||||
|
&relayers_state,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,8 +959,9 @@ mod tests {
|
|||||||
message, message_payload, run_test, unrewarded_relayer, AccountId, DbWeight,
|
message, message_payload, run_test, unrewarded_relayer, AccountId, DbWeight,
|
||||||
RuntimeEvent as TestEvent, RuntimeOrigin, TestDeliveryConfirmationPayments,
|
RuntimeEvent as TestEvent, RuntimeOrigin, TestDeliveryConfirmationPayments,
|
||||||
TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRelayer,
|
TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRelayer,
|
||||||
TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD,
|
TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN,
|
||||||
TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B,
|
REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A,
|
||||||
|
TEST_RELAYER_B,
|
||||||
};
|
};
|
||||||
use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState};
|
use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState};
|
||||||
use bp_test_utils::generate_owned_bridge_module_tests;
|
use bp_test_utils::generate_owned_bridge_module_tests;
|
||||||
@@ -1398,50 +1418,78 @@ mod tests {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// this reports delivery of message 1 => reward is paid to TEST_RELAYER_A
|
// this reports delivery of message 1 => reward is paid to TEST_RELAYER_A
|
||||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
let single_message_delivery_proof = TestMessagesDeliveryProof(Ok((
|
||||||
RuntimeOrigin::signed(1),
|
|
||||||
TestMessagesDeliveryProof(Ok((
|
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)]
|
relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(),
|
||||||
.into_iter()
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
))),
|
)));
|
||||||
|
let single_message_delivery_proof_size = single_message_delivery_proof.size();
|
||||||
|
let result = Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||||
|
RuntimeOrigin::signed(1),
|
||||||
|
single_message_delivery_proof,
|
||||||
UnrewardedRelayersState {
|
UnrewardedRelayersState {
|
||||||
unrewarded_relayer_entries: 1,
|
unrewarded_relayer_entries: 1,
|
||||||
total_messages: 1,
|
total_messages: 1,
|
||||||
last_delivered_nonce: 1,
|
last_delivered_nonce: 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
));
|
);
|
||||||
|
assert_ok!(result);
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap().actual_weight.unwrap(),
|
||||||
|
TestWeightInfo::receive_messages_delivery_proof_weight(
|
||||||
|
&PreComputedSize(single_message_delivery_proof_size as _),
|
||||||
|
&UnrewardedRelayersState {
|
||||||
|
unrewarded_relayer_entries: 1,
|
||||||
|
total_messages: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
||||||
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
||||||
|
|
||||||
// this reports delivery of both message 1 and message 2 => reward is paid only to
|
// this reports delivery of both message 1 and message 2 => reward is paid only to
|
||||||
// TEST_RELAYER_B
|
// TEST_RELAYER_B
|
||||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
let two_messages_delivery_proof = TestMessagesDeliveryProof(Ok((
|
||||||
RuntimeOrigin::signed(1),
|
|
||||||
TestMessagesDeliveryProof(Ok((
|
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
relayers: vec![
|
relayers: vec![
|
||||||
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||||
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
unrewarded_relayer(2, 2, TEST_RELAYER_B),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
))),
|
)));
|
||||||
|
let two_messages_delivery_proof_size = two_messages_delivery_proof.size();
|
||||||
|
let result = Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||||
|
RuntimeOrigin::signed(1),
|
||||||
|
two_messages_delivery_proof,
|
||||||
UnrewardedRelayersState {
|
UnrewardedRelayersState {
|
||||||
unrewarded_relayer_entries: 2,
|
unrewarded_relayer_entries: 2,
|
||||||
total_messages: 2,
|
total_messages: 2,
|
||||||
last_delivered_nonce: 2,
|
last_delivered_nonce: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
));
|
);
|
||||||
|
assert_ok!(result);
|
||||||
|
// even though the pre-dispatch weight was for two messages, the actual weight is
|
||||||
|
// for single message only
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap().actual_weight.unwrap(),
|
||||||
|
TestWeightInfo::receive_messages_delivery_proof_weight(
|
||||||
|
&PreComputedSize(two_messages_delivery_proof_size as _),
|
||||||
|
&UnrewardedRelayersState {
|
||||||
|
unrewarded_relayer_entries: 1,
|
||||||
|
total_messages: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1));
|
||||||
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -148,9 +148,12 @@ parameter_types! {
|
|||||||
pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID, TEST_LANE_ID_2];
|
pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID, TEST_LANE_ID_2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// weights of messages pallet calls we use in tests.
|
||||||
|
pub type TestWeightInfo = ();
|
||||||
|
|
||||||
impl Config for TestRuntime {
|
impl Config for TestRuntime {
|
||||||
type RuntimeEvent = RuntimeEvent;
|
type RuntimeEvent = RuntimeEvent;
|
||||||
type WeightInfo = ();
|
type WeightInfo = TestWeightInfo;
|
||||||
type ActiveOutboundLanes = ActiveOutboundLanes;
|
type ActiveOutboundLanes = ActiveOutboundLanes;
|
||||||
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
|
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
|
||||||
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
|
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
|
||||||
@@ -381,12 +384,15 @@ impl DeliveryConfirmationPayments<AccountId> for TestDeliveryConfirmationPayment
|
|||||||
messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
||||||
_confirmation_relayer: &AccountId,
|
_confirmation_relayer: &AccountId,
|
||||||
received_range: &RangeInclusive<MessageNonce>,
|
received_range: &RangeInclusive<MessageNonce>,
|
||||||
) {
|
) -> MessageNonce {
|
||||||
let relayers_rewards = calc_relayers_rewards(messages_relayers, received_range);
|
let relayers_rewards = calc_relayers_rewards(messages_relayers, received_range);
|
||||||
|
let rewarded_relayers = relayers_rewards.len();
|
||||||
for (relayer, reward) in &relayers_rewards {
|
for (relayer, reward) in &relayers_rewards {
|
||||||
let key = (b":relayer-reward:", relayer, reward).encode();
|
let key = (b":relayer-reward:", relayer, reward).encode();
|
||||||
frame_support::storage::unhashed::put(&key, &true);
|
frame_support::storage::unhashed::put(&key, &true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rewarded_relayers as _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use crate::{Config, Pallet};
|
|||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{DeliveryConfirmationPayments, RelayersRewards},
|
source_chain::{DeliveryConfirmationPayments, RelayersRewards},
|
||||||
LaneId,
|
LaneId, MessageNonce,
|
||||||
};
|
};
|
||||||
use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
|
use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
|
||||||
use frame_support::{sp_runtime::SaturatedConversion, traits::Get};
|
use frame_support::{sp_runtime::SaturatedConversion, traits::Get};
|
||||||
@@ -47,9 +47,10 @@ where
|
|||||||
messages_relayers: VecDeque<bp_messages::UnrewardedRelayer<T::AccountId>>,
|
messages_relayers: VecDeque<bp_messages::UnrewardedRelayer<T::AccountId>>,
|
||||||
confirmation_relayer: &T::AccountId,
|
confirmation_relayer: &T::AccountId,
|
||||||
received_range: &RangeInclusive<bp_messages::MessageNonce>,
|
received_range: &RangeInclusive<bp_messages::MessageNonce>,
|
||||||
) {
|
) -> MessageNonce {
|
||||||
let relayers_rewards =
|
let relayers_rewards =
|
||||||
bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range);
|
bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range);
|
||||||
|
let rewarded_relayers = relayers_rewards.len();
|
||||||
|
|
||||||
register_relayers_rewards::<T>(
|
register_relayers_rewards::<T>(
|
||||||
confirmation_relayer,
|
confirmation_relayer,
|
||||||
@@ -61,6 +62,8 @@ where
|
|||||||
),
|
),
|
||||||
DeliveryReward::get(),
|
DeliveryReward::get(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rewarded_relayers as _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,12 +98,14 @@ pub trait DeliveryConfirmationPayments<AccountId> {
|
|||||||
///
|
///
|
||||||
/// The implementation may also choose to pay reward to the `confirmation_relayer`, which is
|
/// The implementation may also choose to pay reward to the `confirmation_relayer`, which is
|
||||||
/// a relayer that has submitted delivery confirmation transaction.
|
/// a relayer that has submitted delivery confirmation transaction.
|
||||||
|
///
|
||||||
|
/// Returns number of actually rewarded relayers.
|
||||||
fn pay_reward(
|
fn pay_reward(
|
||||||
lane_id: LaneId,
|
lane_id: LaneId,
|
||||||
messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
||||||
confirmation_relayer: &AccountId,
|
confirmation_relayer: &AccountId,
|
||||||
received_range: &RangeInclusive<MessageNonce>,
|
received_range: &RangeInclusive<MessageNonce>,
|
||||||
);
|
) -> MessageNonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AccountId> DeliveryConfirmationPayments<AccountId> for () {
|
impl<AccountId> DeliveryConfirmationPayments<AccountId> for () {
|
||||||
@@ -114,8 +116,9 @@ impl<AccountId> DeliveryConfirmationPayments<AccountId> for () {
|
|||||||
_messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
_messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
||||||
_confirmation_relayer: &AccountId,
|
_confirmation_relayer: &AccountId,
|
||||||
_received_range: &RangeInclusive<MessageNonce>,
|
_received_range: &RangeInclusive<MessageNonce>,
|
||||||
) {
|
) -> MessageNonce {
|
||||||
// this implementation is not rewarding relayers at all
|
// this implementation is not rewarding relayers at all
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +205,7 @@ impl<AccountId> DeliveryConfirmationPayments<AccountId> for ForbidOutboundMessag
|
|||||||
_messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
_messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
|
||||||
_confirmation_relayer: &AccountId,
|
_confirmation_relayer: &AccountId,
|
||||||
_received_range: &RangeInclusive<MessageNonce>,
|
_received_range: &RangeInclusive<MessageNonce>,
|
||||||
) {
|
) -> MessageNonce {
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user