mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 13:21:01 +00:00
Custom relay strategy (#1198)
* Add relayer strategy * Add default relayer strategy * default relayer strategy * expose relayer strategy * fix compile * fix compile * docs * Rename Relayer to Relay, keep RelayerDecide * split `DefaultRelayerStrategy` into `AltruisticRelayerStrategy` and `RationalRelayerStrategy` * Remove relayer mode * Remove unused import * Rename `RelayerStrategy` to `RelayStrategy` * Add missing docs * clippy * clippy * clippy * clippy * Revert `relayer_mode` and add `MixStrategy` * Add `EnforcementStrategy` * fix bug and simplify relay strategy * Update message_lane_loop.rs * Update messages_target.rs * clippy * clippy * clippy * clippy * clippy * clippy * clippy * fix test * fix test * test test test fix test
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// 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/>.
|
||||
|
||||
//! Altruistic relay strategy
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
message_lane::MessageLane,
|
||||
message_lane_loop::{
|
||||
SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient,
|
||||
},
|
||||
relay_strategy::{RelayReference, RelayStrategy},
|
||||
};
|
||||
|
||||
/// The relayer doesn't care about rewards.
|
||||
#[derive(Clone)]
|
||||
pub struct AltruisticStrategy;
|
||||
|
||||
#[async_trait]
|
||||
impl RelayStrategy for AltruisticStrategy {
|
||||
async fn decide<
|
||||
P: MessageLane,
|
||||
SourceClient: MessageLaneSourceClient<P>,
|
||||
TargetClient: MessageLaneTargetClient<P>,
|
||||
>(
|
||||
&self,
|
||||
_reference: &mut RelayReference<P, SourceClient, TargetClient>,
|
||||
) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
// 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 bp_messages::{MessageNonce, Weight};
|
||||
use bp_runtime::messages::DispatchFeePayment;
|
||||
|
||||
use crate::{
|
||||
message_lane::MessageLane,
|
||||
message_lane_loop::{
|
||||
MessageDetails, SourceClient as MessageLaneSourceClient,
|
||||
TargetClient as MessageLaneTargetClient,
|
||||
},
|
||||
message_race_loop::NoncesRange,
|
||||
relay_strategy::{RelayMessagesBatchReference, RelayReference, RelayStrategy},
|
||||
};
|
||||
|
||||
/// Do hard check and run soft check strategy
|
||||
#[derive(Clone)]
|
||||
pub struct EnforcementStrategy<Strategy: RelayStrategy> {
|
||||
strategy: Strategy,
|
||||
}
|
||||
|
||||
impl<Strategy: RelayStrategy> EnforcementStrategy<Strategy> {
|
||||
pub fn new(strategy: Strategy) -> Self {
|
||||
Self { strategy }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Strategy: RelayStrategy> EnforcementStrategy<Strategy> {
|
||||
pub async fn decide<
|
||||
P: MessageLane,
|
||||
SourceClient: MessageLaneSourceClient<P>,
|
||||
TargetClient: MessageLaneTargetClient<P>,
|
||||
>(
|
||||
&self,
|
||||
reference: RelayMessagesBatchReference<P, SourceClient, TargetClient>,
|
||||
) -> Option<MessageNonce> {
|
||||
let mut hard_selected_count = 0;
|
||||
let mut soft_selected_count = 0;
|
||||
|
||||
let mut selected_weight: Weight = 0;
|
||||
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(),
|
||||
|
||||
selected_reward: P::SourceChainBalance::zero(),
|
||||
selected_cost: P::SourceChainBalance::zero(),
|
||||
selected_size: 0,
|
||||
|
||||
total_reward: P::SourceChainBalance::zero(),
|
||||
total_confirmations_cost: P::SourceChainBalance::zero(),
|
||||
total_cost: P::SourceChainBalance::zero(),
|
||||
|
||||
hard_selected_begin_nonce,
|
||||
selected_prepaid_nonces: 0,
|
||||
selected_unpaid_weight: 0,
|
||||
|
||||
index: 0,
|
||||
nonce: 0,
|
||||
details: MessageDetails {
|
||||
dispatch_weight: 0,
|
||||
size: 0,
|
||||
reward: P::SourceChainBalance::zero(),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||
},
|
||||
};
|
||||
|
||||
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 <= 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;
|
||||
|
||||
// If dispatch fee has been paid at the source chain, it means that it is **relayer**
|
||||
// who's paying for dispatch at the target chain AND reward must cover this dispatch
|
||||
// fee.
|
||||
//
|
||||
// If dispatch fee is paid at the target chain, it means that it'll be withdrawn from
|
||||
// the dispatch origin account AND reward is not covering this fee.
|
||||
//
|
||||
// So in the latter case we're not adding the dispatch weight to the delivery
|
||||
// transaction weight.
|
||||
let mut new_selected_prepaid_nonces = relay_reference.selected_prepaid_nonces;
|
||||
let new_selected_unpaid_weight = match details.dispatch_fee_payment {
|
||||
DispatchFeePayment::AtSourceChain => {
|
||||
new_selected_prepaid_nonces += 1;
|
||||
relay_reference.selected_unpaid_weight.saturating_add(details.dispatch_weight)
|
||||
},
|
||||
DispatchFeePayment::AtTargetChain => relay_reference.selected_unpaid_weight,
|
||||
};
|
||||
relay_reference.selected_prepaid_nonces = new_selected_prepaid_nonces;
|
||||
relay_reference.selected_unpaid_weight = new_selected_unpaid_weight;
|
||||
|
||||
// now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT
|
||||
// to deliver it? It depends on the relayer strategy.
|
||||
if self.strategy.decide(&mut relay_reference).await {
|
||||
soft_selected_count = index + 1;
|
||||
}
|
||||
|
||||
hard_selected_count = index + 1;
|
||||
selected_weight = new_selected_weight;
|
||||
selected_count = new_selected_count;
|
||||
}
|
||||
|
||||
if hard_selected_count != soft_selected_count {
|
||||
let hard_selected_end_nonce =
|
||||
hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1;
|
||||
let soft_selected_begin_nonce = hard_selected_begin_nonce;
|
||||
let soft_selected_end_nonce =
|
||||
soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1;
|
||||
log::warn!(
|
||||
target: "bridge",
|
||||
"Relayer may deliver nonces [{:?}; {:?}], but because of its strategy it has selected \
|
||||
nonces [{:?}; {:?}].",
|
||||
hard_selected_begin_nonce,
|
||||
hard_selected_end_nonce,
|
||||
soft_selected_begin_nonce,
|
||||
soft_selected_end_nonce,
|
||||
);
|
||||
|
||||
hard_selected_count = soft_selected_count;
|
||||
}
|
||||
|
||||
if hard_selected_count != 0 {
|
||||
if relay_reference.selected_reward != P::SourceChainBalance::zero() &&
|
||||
relay_reference.selected_cost != P::SourceChainBalance::zero()
|
||||
{
|
||||
log::trace!(
|
||||
target: "bridge",
|
||||
"Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}",
|
||||
hard_selected_begin_nonce,
|
||||
hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1,
|
||||
&relay_reference.selected_reward,
|
||||
&relay_reference.selected_cost,
|
||||
relay_reference.selected_reward - relay_reference.selected_cost,
|
||||
);
|
||||
}
|
||||
|
||||
Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
message_lane::MessageLane,
|
||||
message_lane_loop::{
|
||||
RelayerMode, SourceClient as MessageLaneSourceClient,
|
||||
TargetClient as MessageLaneTargetClient,
|
||||
},
|
||||
relay_strategy::{AltruisticStrategy, RationalStrategy, RelayReference, RelayStrategy},
|
||||
};
|
||||
|
||||
/// The relayer doesn't care about rewards.
|
||||
#[derive(Clone)]
|
||||
pub struct MixStrategy {
|
||||
relayer_mode: RelayerMode,
|
||||
}
|
||||
|
||||
impl MixStrategy {
|
||||
/// Create mix strategy instance
|
||||
pub fn new(relayer_mode: RelayerMode) -> Self {
|
||||
Self { relayer_mode }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RelayStrategy for MixStrategy {
|
||||
async fn decide<
|
||||
P: MessageLane,
|
||||
SourceClient: MessageLaneSourceClient<P>,
|
||||
TargetClient: MessageLaneTargetClient<P>,
|
||||
>(
|
||||
&self,
|
||||
reference: &mut RelayReference<P, SourceClient, TargetClient>,
|
||||
) -> bool {
|
||||
match self.relayer_mode {
|
||||
RelayerMode::Altruistic => AltruisticStrategy.decide(reference).await,
|
||||
RelayerMode::Rational => RationalStrategy.decide(reference).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// 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/>.
|
||||
|
||||
//! Relayer strategy
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use bp_messages::{MessageNonce, Weight};
|
||||
|
||||
use crate::{
|
||||
message_lane::MessageLane,
|
||||
message_lane_loop::{
|
||||
MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient,
|
||||
TargetClient as MessageLaneTargetClient,
|
||||
},
|
||||
message_race_strategy::SourceRangesQueue,
|
||||
};
|
||||
|
||||
pub(crate) use self::enforcement_strategy::*;
|
||||
pub use self::{altruistic_strategy::*, mix_strategy::*, rational_strategy::*};
|
||||
|
||||
mod altruistic_strategy;
|
||||
mod enforcement_strategy;
|
||||
mod mix_strategy;
|
||||
mod rational_strategy;
|
||||
|
||||
/// Relayer strategy trait
|
||||
#[async_trait]
|
||||
pub trait RelayStrategy: 'static + Clone + Send + Sync {
|
||||
/// The relayer decide how to process nonce by reference.
|
||||
/// From given set of source nonces, that are ready to be delivered, select nonces
|
||||
/// to fit into single delivery transaction.
|
||||
///
|
||||
/// The function returns last nonce that must be delivered to the target chain.
|
||||
async fn decide<
|
||||
P: MessageLane,
|
||||
SourceClient: MessageLaneSourceClient<P>,
|
||||
TargetClient: MessageLaneTargetClient<P>,
|
||||
>(
|
||||
&self,
|
||||
reference: &mut RelayReference<P, SourceClient, TargetClient>,
|
||||
) -> bool;
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// Current block reward summary
|
||||
pub selected_reward: P::SourceChainBalance,
|
||||
/// Current block cost summary
|
||||
pub selected_cost: P::SourceChainBalance,
|
||||
/// Messages size summary
|
||||
pub selected_size: u32,
|
||||
|
||||
/// Current block reward summary
|
||||
pub total_reward: P::SourceChainBalance,
|
||||
/// All confirmations cost
|
||||
pub total_confirmations_cost: P::SourceChainBalance,
|
||||
/// Current block cost summary
|
||||
pub total_cost: P::SourceChainBalance,
|
||||
|
||||
/// Hard check begin nonce
|
||||
pub hard_selected_begin_nonce: MessageNonce,
|
||||
/// Count prepaid nonces
|
||||
pub selected_prepaid_nonces: MessageNonce,
|
||||
/// Unpaid nonces weight summary
|
||||
pub selected_unpaid_weight: Weight,
|
||||
|
||||
/// 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,
|
||||
/// Source queue.
|
||||
pub nonces_queue: SourceRangesQueue<
|
||||
P::SourceHeaderHash,
|
||||
P::SourceHeaderNumber,
|
||||
MessageDetailsMap<P::SourceChainBalance>,
|
||||
>,
|
||||
/// Source queue range
|
||||
pub nonces_queue_range: Range<usize>,
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
// 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/>.
|
||||
|
||||
//! Rational relay strategy
|
||||
|
||||
use async_trait::async_trait;
|
||||
use num_traits::SaturatingAdd;
|
||||
|
||||
use bp_messages::MessageNonce;
|
||||
|
||||
use crate::{
|
||||
message_lane::MessageLane,
|
||||
message_lane_loop::{
|
||||
SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient,
|
||||
},
|
||||
relay_strategy::{RelayReference, RelayStrategy},
|
||||
};
|
||||
|
||||
/// The relayer will deliver all messages and confirmations as long as he's not losing any
|
||||
/// funds.
|
||||
#[derive(Clone)]
|
||||
pub struct RationalStrategy;
|
||||
|
||||
#[async_trait]
|
||||
impl RelayStrategy for RationalStrategy {
|
||||
async fn decide<
|
||||
P: MessageLane,
|
||||
SourceClient: MessageLaneSourceClient<P>,
|
||||
TargetClient: MessageLaneTargetClient<P>,
|
||||
>(
|
||||
&self,
|
||||
reference: &mut RelayReference<P, SourceClient, TargetClient>,
|
||||
) -> bool {
|
||||
// technically, multiple confirmations will be delivered in a single transaction,
|
||||
// meaning less loses for relayer. But here we don't know the final relayer yet, so
|
||||
// we're adding a separate transaction for every message. Normally, this cost is covered
|
||||
// by the message sender. Probably reconsider this?
|
||||
let confirmation_transaction_cost =
|
||||
reference.lane_source_client.estimate_confirmation_transaction().await;
|
||||
|
||||
let delivery_transaction_cost = match reference
|
||||
.lane_target_client
|
||||
.estimate_delivery_transaction_in_source_tokens(
|
||||
reference.hard_selected_begin_nonce..=
|
||||
(reference.hard_selected_begin_nonce + reference.index as MessageNonce),
|
||||
reference.selected_prepaid_nonces,
|
||||
reference.selected_unpaid_weight,
|
||||
reference.selected_size as u32,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
log::debug!(
|
||||
target: "bridge",
|
||||
"Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery",
|
||||
err,
|
||||
);
|
||||
return false
|
||||
},
|
||||
};
|
||||
|
||||
// if it is the first message that makes reward less than cost, let's log it
|
||||
// if this message makes batch profitable again, let's log it
|
||||
let is_total_reward_less_than_cost = reference.total_reward < reference.total_cost;
|
||||
let prev_total_cost = reference.total_cost;
|
||||
let prev_total_reward = reference.total_reward;
|
||||
reference.total_confirmations_cost = reference
|
||||
.total_confirmations_cost
|
||||
.saturating_add(&confirmation_transaction_cost);
|
||||
reference.total_reward = reference.total_reward.saturating_add(&reference.details.reward);
|
||||
reference.total_cost =
|
||||
reference.total_confirmations_cost.saturating_add(&delivery_transaction_cost);
|
||||
if !is_total_reward_less_than_cost && reference.total_reward < reference.total_cost {
|
||||
log::debug!(
|
||||
target: "bridge",
|
||||
"Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \
|
||||
total reward {:?}->{:?}",
|
||||
reference.nonce,
|
||||
reference.details.reward,
|
||||
prev_total_cost,
|
||||
reference.total_cost,
|
||||
prev_total_reward,
|
||||
reference.total_reward,
|
||||
);
|
||||
} else if is_total_reward_less_than_cost && reference.total_reward >= reference.total_cost {
|
||||
log::debug!(
|
||||
target: "bridge",
|
||||
"Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \
|
||||
equal to the total reward {:?}->{:?} (again)",
|
||||
reference.nonce,
|
||||
reference.details.reward,
|
||||
prev_total_cost,
|
||||
reference.total_cost,
|
||||
prev_total_reward,
|
||||
reference.total_reward,
|
||||
);
|
||||
}
|
||||
|
||||
// Rational relayer never want to lose his funds
|
||||
if reference.total_reward >= reference.total_cost {
|
||||
reference.selected_reward = reference.total_reward;
|
||||
reference.selected_cost = reference.total_cost;
|
||||
return true
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user