Files
pezkuwi-subxt/bridges/relays/messages/src/message_race_limits.rs
T
Svyatoslav Nikolsky 8c845602cf Remove message fee + message send calls (#1642)
* remove message fee

* it is compiling!

* fixes + fmt

* more cleanup

* more cleanup

* restore MessageDeliveryAndDispatchPayment since we'll need relayer rewards

* started rational relayer removal

* more removal

* removed estimate fee subcommand

* remove DispatchFeePayment

* more removals

* removed conversion rates && some metrics

* - unneeded associated type

* - OutboundMessageFee

* fix benchmarks compilation

* fmt

* test + fix benchmarks

* fix send message

* clippy
2024-04-10 10:28:37 +02:00

201 lines
6.4 KiB
Rust

// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! enforcement strategy
use num_traits::Zero;
use std::ops::Range;
use bp_messages::{MessageNonce, Weight};
use crate::{
message_lane::MessageLane,
message_lane_loop::{
MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient,
TargetClient as MessageLaneTargetClient,
},
message_race_loop::NoncesRange,
message_race_strategy::SourceRangesQueue,
metrics::MessageLaneLoopMetrics,
};
/// Reference data for participating in relay
pub struct RelayReference<
P: MessageLane,
SourceClient: MessageLaneSourceClient<P>,
TargetClient: MessageLaneTargetClient<P>,
> {
/// The client that is connected to the message lane source node.
pub lane_source_client: SourceClient,
/// The client that is connected to the message lane target node.
pub lane_target_client: TargetClient,
/// Metrics reference.
pub metrics: Option<MessageLaneLoopMetrics>,
/// Messages size summary
pub selected_size: u32,
/// Hard check begin nonce
pub hard_selected_begin_nonce: MessageNonce,
/// Index by all ready nonces
pub index: usize,
/// Current nonce
pub nonce: MessageNonce,
/// Current nonce details
pub details: MessageDetails<P::SourceChainBalance>,
}
/// Relay reference data
pub struct RelayMessagesBatchReference<
P: MessageLane,
SourceClient: MessageLaneSourceClient<P>,
TargetClient: MessageLaneTargetClient<P>,
> {
/// Maximal number of relayed messages in single delivery transaction.
pub max_messages_in_this_batch: MessageNonce,
/// Maximal cumulative dispatch weight of relayed messages in single delivery transaction.
pub max_messages_weight_in_single_batch: Weight,
/// Maximal cumulative size of relayed messages in single delivery transaction.
pub max_messages_size_in_single_batch: u32,
/// The client that is connected to the message lane source node.
pub lane_source_client: SourceClient,
/// The client that is connected to the message lane target node.
pub lane_target_client: TargetClient,
/// Metrics reference.
pub metrics: Option<MessageLaneLoopMetrics>,
/// Source queue.
pub nonces_queue: SourceRangesQueue<
P::SourceHeaderHash,
P::SourceHeaderNumber,
MessageDetailsMap<P::SourceChainBalance>,
>,
/// Source queue range
pub nonces_queue_range: Range<usize>,
}
/// Limits of the message race transactions.
#[derive(Clone)]
pub struct MessageRaceLimits;
impl MessageRaceLimits {
pub async fn decide<
P: MessageLane,
SourceClient: MessageLaneSourceClient<P>,
TargetClient: MessageLaneTargetClient<P>,
>(
reference: RelayMessagesBatchReference<P, SourceClient, TargetClient>,
) -> Option<MessageNonce> {
let mut hard_selected_count = 0;
let mut selected_weight = Weight::zero();
let mut selected_count: MessageNonce = 0;
let hard_selected_begin_nonce =
reference.nonces_queue[reference.nonces_queue_range.start].1.begin();
// relay reference
let mut relay_reference = RelayReference {
lane_source_client: reference.lane_source_client.clone(),
lane_target_client: reference.lane_target_client.clone(),
metrics: reference.metrics.clone(),
selected_size: 0,
hard_selected_begin_nonce,
index: 0,
nonce: 0,
details: MessageDetails {
dispatch_weight: Weight::zero(),
size: 0,
reward: P::SourceChainBalance::zero(),
},
};
let all_ready_nonces = reference
.nonces_queue
.range(reference.nonces_queue_range.clone())
.flat_map(|(_, ready_nonces)| ready_nonces.iter())
.enumerate();
for (index, (nonce, details)) in all_ready_nonces {
relay_reference.index = index;
relay_reference.nonce = *nonce;
relay_reference.details = *details;
// Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch`
// and `max_messages_size_in_single_batch`, we may still try to submit transaction
// with single message if message overflows these limits. The worst case would be if
// transaction will be rejected by the target runtime, but at least we have tried.
// limit messages in the batch by weight
let new_selected_weight = match selected_weight.checked_add(&details.dispatch_weight) {
Some(new_selected_weight)
if new_selected_weight
.all_lte(reference.max_messages_weight_in_single_batch) =>
new_selected_weight,
new_selected_weight if selected_count == 0 => {
log::warn!(
target: "bridge",
"Going to submit message delivery transaction with declared dispatch \
weight {:?} that overflows maximal configured weight {}",
new_selected_weight,
reference.max_messages_weight_in_single_batch,
);
new_selected_weight.unwrap_or(Weight::MAX)
},
_ => break,
};
// limit messages in the batch by size
let new_selected_size = match relay_reference.selected_size.checked_add(details.size) {
Some(new_selected_size)
if new_selected_size <= reference.max_messages_size_in_single_batch =>
new_selected_size,
new_selected_size if selected_count == 0 => {
log::warn!(
target: "bridge",
"Going to submit message delivery transaction with message \
size {:?} that overflows maximal configured size {}",
new_selected_size,
reference.max_messages_size_in_single_batch,
);
new_selected_size.unwrap_or(u32::MAX)
},
_ => break,
};
// limit number of messages in the batch
let new_selected_count = selected_count + 1;
if new_selected_count > reference.max_messages_in_this_batch {
break
}
relay_reference.selected_size = new_selected_size;
hard_selected_count = index + 1;
selected_weight = new_selected_weight;
selected_count = new_selected_count;
}
if hard_selected_count != 0 {
let selected_max_nonce =
hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1;
Some(selected_max_nonce)
} else {
None
}
}
}