Match substrate's fmt (#1148)

* Alter gitlab.

* Use substrate's rustfmt.toml

* cargo +nightly fmt --all

* Fix spellcheck.

* cargo +nightly fmt --all

* format.

* Fix spellcheck and fmt

* fmt?

* Fix spellcheck

Co-authored-by: Tomasz Drwięga <tomasz@parity.io>
This commit is contained in:
hacpy
2021-09-24 19:29:31 +08:00
committed by Bastian Köcher
parent 87cbb382d9
commit bd70de8b8b
174 changed files with 6095 additions and 4962 deletions
+4 -2
View File
@@ -61,7 +61,9 @@ pub trait MessageLane: 'static + Clone + Send + Sync {
}
/// Source header id within given one-way message lane.
pub type SourceHeaderIdOf<P> = HeaderId<<P as MessageLane>::SourceHeaderHash, <P as MessageLane>::SourceHeaderNumber>;
pub type SourceHeaderIdOf<P> =
HeaderId<<P as MessageLane>::SourceHeaderHash, <P as MessageLane>::SourceHeaderNumber>;
/// Target header id within given one-way message lane.
pub type TargetHeaderIdOf<P> = HeaderId<<P as MessageLane>::TargetHeaderHash, <P as MessageLane>::TargetHeaderNumber>;
pub type TargetHeaderIdOf<P> =
HeaderId<<P as MessageLane>::TargetHeaderHash, <P as MessageLane>::TargetHeaderNumber>;
@@ -24,10 +24,12 @@
//! finalized header. I.e. when talking about headers in lane context, we
//! only care about finalized headers.
use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf};
use crate::message_race_delivery::run as run_message_delivery_race;
use crate::message_race_receiving::run as run_message_receiving_race;
use crate::metrics::MessageLaneLoopMetrics;
use crate::{
message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf},
message_race_delivery::run as run_message_delivery_race,
message_race_receiving::run as run_message_receiving_race,
metrics::MessageLaneLoopMetrics,
};
use async_trait::async_trait;
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight};
@@ -64,20 +66,22 @@ pub struct Params {
pub enum RelayerMode {
/// The relayer doesn't care about rewards.
Altruistic,
/// The relayer will deliver all messages and confirmations as long as he's not losing any funds.
/// The relayer will deliver all messages and confirmations as long as he's not losing any
/// funds.
Rational,
}
/// Message delivery race parameters.
#[derive(Debug, Clone)]
pub struct MessageDeliveryParams {
/// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number of entries
/// in the `InboundLaneData::relayers` set, all new messages will be rejected until reward payment will
/// be proved (by including outbound lane state to the message delivery transaction).
/// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number
/// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until
/// reward payment will be proved (by including outbound lane state to the message delivery
/// transaction).
pub max_unrewarded_relayer_entries_at_target: MessageNonce,
/// Message delivery race will stop delivering messages if there are `max_unconfirmed_nonces_at_target`
/// unconfirmed nonces on the target node. The race would continue once they're confirmed by the
/// receiving race.
/// Message delivery race will stop delivering messages if there are
/// `max_unconfirmed_nonces_at_target` unconfirmed nonces on the target node. The race would
/// continue once they're confirmed by the receiving race.
pub max_unconfirmed_nonces_at_target: MessageNonce,
/// Maximal number of relayed messages in single delivery transaction.
pub max_messages_in_single_batch: MessageNonce,
@@ -103,7 +107,8 @@ pub struct MessageDetails<SourceChainBalance> {
}
/// Messages details map.
pub type MessageDetailsMap<SourceChainBalance> = BTreeMap<MessageNonce, MessageDetails<SourceChainBalance>>;
pub type MessageDetailsMap<SourceChainBalance> =
BTreeMap<MessageNonce, MessageDetails<SourceChainBalance>>;
/// Message delivery race proof parameters.
#[derive(Debug, PartialEq)]
@@ -225,7 +230,8 @@ pub struct ClientState<SelfHeaderId, PeerHeaderId> {
pub best_self: SelfHeaderId,
/// Best finalized header id of this chain.
pub best_finalized_self: SelfHeaderId,
/// Best finalized header id of the peer chain read at the best block of this chain (at `best_finalized_self`).
/// Best finalized header id of the peer chain read at the best block of this chain (at
/// `best_finalized_self`).
pub best_finalized_peer_at_best_self: PeerHeaderId,
}
@@ -244,14 +250,10 @@ pub struct ClientsState<P: MessageLane> {
pub target: Option<TargetClientState<P>>,
}
/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop.
/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs
/// sync loop.
pub fn metrics_prefix<P: MessageLane>(lane: &LaneId) -> String {
format!(
"{}_to_{}_MessageLane_{}",
P::SOURCE_NAME,
P::TARGET_NAME,
hex::encode(lane)
)
format!("{}_to_{}_MessageLane_{}", P::SOURCE_NAME, P::TARGET_NAME, hex::encode(lane))
}
/// Run message lane service loop.
@@ -270,22 +272,20 @@ pub async fn run<P: MessageLane>(
.standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))?
.expose()
.await?
.run(
metrics_prefix::<P>(&params.lane),
move |source_client, target_client, metrics| {
run_until_connection_lost(
params.clone(),
source_client,
target_client,
metrics,
exit_signal.clone(),
)
},
)
.run(metrics_prefix::<P>(&params.lane), move |source_client, target_client, metrics| {
run_until_connection_lost(
params.clone(),
source_client,
target_client,
metrics,
exit_signal.clone(),
)
})
.await
}
/// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received.
/// Run one-way message delivery loop until connection with target or source node is lost, or exit
/// signal is received.
async fn run_until_connection_lost<P: MessageLane, SC: SourceClient<P>, TC: TargetClient<P>>(
params: Params,
source_client: SC,
@@ -557,7 +557,7 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_source_fails {
return Err(TestError);
return Err(TestError)
}
Ok(data.source_state.clone())
}
@@ -569,7 +569,7 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_source_fails {
return Err(TestError);
return Err(TestError)
}
Ok((id, data.source_latest_generated_nonce))
}
@@ -609,11 +609,7 @@ pub(crate) mod tests {
nonces: RangeInclusive<MessageNonce>,
proof_parameters: MessageProofParameters,
) -> Result<
(
SourceHeaderIdOf<TestMessageLane>,
RangeInclusive<MessageNonce>,
TestMessagesProof,
),
(SourceHeaderIdOf<TestMessageLane>, RangeInclusive<MessageNonce>, TestMessagesProof),
TestError,
> {
let mut data = self.data.lock();
@@ -694,7 +690,7 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_target_fails {
return Err(TestError);
return Err(TestError)
}
Ok(data.target_state.clone())
}
@@ -706,7 +702,7 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_target_fails {
return Err(TestError);
return Err(TestError)
}
Ok((id, data.target_latest_received_nonce))
}
@@ -732,7 +728,7 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_target_fails {
return Err(TestError);
return Err(TestError)
}
Ok((id, data.target_latest_confirmed_received_nonce))
}
@@ -753,14 +749,15 @@ pub(crate) mod tests {
let mut data = self.data.lock();
(self.tick)(&mut *data);
if data.is_target_fails {
return Err(TestError);
return Err(TestError)
}
data.target_state.best_self =
HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1);
data.target_state.best_finalized_self = data.target_state.best_self;
data.target_latest_received_nonce = *proof.0.end();
if let Some(target_latest_confirmed_received_nonce) = proof.1 {
data.target_latest_confirmed_received_nonce = target_latest_confirmed_received_nonce;
data.target_latest_confirmed_received_nonce =
target_latest_confirmed_received_nonce;
}
data.submitted_messages_proofs.push(proof);
Ok(nonces)
@@ -780,11 +777,9 @@ pub(crate) mod tests {
total_dispatch_weight: Weight,
total_size: u32,
) -> Result<TestSourceChainBalance, TestError> {
Ok(
BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1)
+ total_dispatch_weight
+ total_size as TestSourceChainBalance,
)
Ok(BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) +
total_dispatch_weight +
total_size as TestSourceChainBalance)
}
}
@@ -797,14 +792,8 @@ pub(crate) mod tests {
async_std::task::block_on(async {
let data = Arc::new(Mutex::new(data));
let source_client = TestSourceClient {
data: data.clone(),
tick: source_tick,
};
let target_client = TestTargetClient {
data: data.clone(),
tick: target_tick,
};
let source_client = TestSourceClient { data: data.clone(), tick: source_tick };
let target_client = TestTargetClient { data: data.clone(), tick: target_tick };
let _ = run(
Params {
lane: [0, 0, 0, 0],
@@ -907,7 +896,10 @@ pub(crate) mod tests {
data.source_state.best_finalized_self = data.source_state.best_self;
// headers relay must only be started when we need new target headers at source node
if data.target_to_source_header_required.is_some() {
assert!(data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_self.0);
assert!(
data.source_state.best_finalized_peer_at_best_self.0 <
data.target_state.best_self.0
);
data.target_to_source_header_required = None;
}
// syncing target headers -> source chain
@@ -924,7 +916,10 @@ pub(crate) mod tests {
data.target_state.best_finalized_self = data.target_state.best_self;
// headers relay must only be started when we need new source headers at target node
if data.source_to_target_header_required.is_some() {
assert!(data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_self.0);
assert!(
data.target_state.best_finalized_peer_at_best_self.0 <
data.source_state.best_self.0
);
data.source_to_target_header_required = None;
}
// syncing source headers -> target chain
@@ -13,18 +13,20 @@
//! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target".
use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf};
use crate::message_lane_loop::{
MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode,
SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient,
TargetClientState,
use crate::{
message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf},
message_lane_loop::{
MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode,
SourceClient as MessageLaneSourceClient, SourceClientState,
TargetClient as MessageLaneTargetClient, TargetClientState,
},
message_race_loop::{
MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces,
TargetClient, TargetClientNonces,
},
message_race_strategy::{BasicStrategy, SourceRangesQueue},
metrics::MessageLaneLoopMetrics,
};
use crate::message_race_loop::{
MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient,
TargetClientNonces,
};
use crate::message_race_strategy::{BasicStrategy, SourceRangesQueue};
use crate::metrics::MessageLaneLoopMetrics;
use async_trait::async_trait;
use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight};
@@ -66,7 +68,8 @@ pub async fn run<P: MessageLane>(
MessageDeliveryStrategy::<P, _, _> {
lane_source_client: source_client,
lane_target_client: target_client,
max_unrewarded_relayer_entries_at_target: params.max_unrewarded_relayer_entries_at_target,
max_unrewarded_relayer_entries_at_target: params
.max_unrewarded_relayer_entries_at_target,
max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target,
max_messages_in_single_batch: params.max_messages_in_single_batch,
max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch,
@@ -121,8 +124,10 @@ where
at_block: SourceHeaderIdOf<P>,
prev_latest_nonce: MessageNonce,
) -> Result<(SourceHeaderIdOf<P>, SourceClientNonces<Self::NoncesRange>), Self::Error> {
let (at_block, latest_generated_nonce) = self.client.latest_generated_nonce(at_block).await?;
let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?;
let (at_block, latest_generated_nonce) =
self.client.latest_generated_nonce(at_block).await?;
let (at_block, latest_confirmed_nonce) =
self.client.latest_confirmed_received_nonce(at_block).await?;
if let Some(metrics_msg) = self.metrics_msg.as_ref() {
metrics_msg.update_source_latest_generated_nonce::<P>(latest_generated_nonce);
@@ -131,7 +136,10 @@ where
let new_nonces = if latest_generated_nonce > prev_latest_nonce {
self.client
.generated_message_details(at_block.clone(), prev_latest_nonce + 1..=latest_generated_nonce)
.generated_message_details(
at_block.clone(),
prev_latest_nonce + 1..=latest_generated_nonce,
)
.await?
} else {
MessageDetailsMap::new()
@@ -139,10 +147,7 @@ where
Ok((
at_block,
SourceClientNonces {
new_nonces,
confirmed_nonce: Some(latest_confirmed_nonce),
},
SourceClientNonces { new_nonces, confirmed_nonce: Some(latest_confirmed_nonce) },
))
}
@@ -151,7 +156,8 @@ where
at_block: SourceHeaderIdOf<P>,
nonces: RangeInclusive<MessageNonce>,
proof_parameters: Self::ProofParameters,
) -> Result<(SourceHeaderIdOf<P>, RangeInclusive<MessageNonce>, P::MessagesProof), Self::Error> {
) -> Result<(SourceHeaderIdOf<P>, RangeInclusive<MessageNonce>, P::MessagesProof), Self::Error>
{
self.client.prove_messages(at_block, nonces, proof_parameters).await
}
}
@@ -180,10 +186,13 @@ where
&self,
at_block: TargetHeaderIdOf<P>,
update_metrics: bool,
) -> Result<(TargetHeaderIdOf<P>, TargetClientNonces<DeliveryRaceTargetNoncesData>), Self::Error> {
) -> Result<(TargetHeaderIdOf<P>, TargetClientNonces<DeliveryRaceTargetNoncesData>), Self::Error>
{
let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?;
let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?;
let (at_block, unrewarded_relayers) = self.client.unrewarded_relayers_state(at_block).await?;
let (at_block, latest_confirmed_nonce) =
self.client.latest_confirmed_received_nonce(at_block).await?;
let (at_block, unrewarded_relayers) =
self.client.unrewarded_relayers_state(at_block).await?;
if update_metrics {
if let Some(metrics_msg) = self.metrics_msg.as_ref() {
@@ -210,9 +219,7 @@ where
nonces: RangeInclusive<MessageNonce>,
proof: P::MessagesProof,
) -> Result<RangeInclusive<MessageNonce>, Self::Error> {
self.client
.submit_messages_proof(generated_at_block, nonces, proof)
.await
self.client.submit_messages_proof(generated_at_block, nonces, proof).await
}
}
@@ -245,7 +252,8 @@ struct MessageDeliveryStrategy<P: MessageLane, SC, TC> {
max_messages_size_in_single_batch: u32,
/// Relayer operating mode.
relayer_mode: RelayerMode,
/// Latest confirmed nonces at the source client + the header id where we have first met this nonce.
/// Latest confirmed nonces at the source client + the header id where we have first met this
/// nonce.
latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf<P>, MessageNonce)>,
/// Target nonces from the source client.
target_nonces: Option<TargetClientNonces<DeliveryRaceTargetNoncesData>>,
@@ -269,23 +277,11 @@ impl<P: MessageLane, SC, TC> std::fmt::Debug for MessageDeliveryStrategy<P, SC,
"max_unrewarded_relayer_entries_at_target",
&self.max_unrewarded_relayer_entries_at_target,
)
.field(
"max_unconfirmed_nonces_at_target",
&self.max_unconfirmed_nonces_at_target,
)
.field("max_unconfirmed_nonces_at_target", &self.max_unconfirmed_nonces_at_target)
.field("max_messages_in_single_batch", &self.max_messages_in_single_batch)
.field(
"max_messages_weight_in_single_batch",
&self.max_messages_weight_in_single_batch,
)
.field(
"max_messages_size_in_single_batch",
&self.max_messages_size_in_single_batch,
)
.field(
"latest_confirmed_nonces_at_source",
&self.latest_confirmed_nonces_at_source,
)
.field("max_messages_weight_in_single_batch", &self.max_messages_weight_in_single_batch)
.field("max_messages_size_in_single_batch", &self.max_messages_size_in_single_batch)
.field("latest_confirmed_nonces_at_source", &self.latest_confirmed_nonces_at_source)
.field("target_nonces", &self.target_nonces)
.field("strategy", &self.strategy)
.finish()
@@ -319,8 +315,12 @@ where
self.strategy.is_empty()
}
fn required_source_header_at_target(&self, current_best: &SourceHeaderIdOf<P>) -> Option<SourceHeaderIdOf<P>> {
let header_required_for_messages_delivery = self.strategy.required_source_header_at_target(current_best);
fn required_source_header_at_target(
&self,
current_best: &SourceHeaderIdOf<P>,
) -> Option<SourceHeaderIdOf<P>> {
let header_required_for_messages_delivery =
self.strategy.required_source_header_at_target(current_best);
let header_required_for_reward_confirmations_delivery =
self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone());
match (
@@ -371,10 +371,7 @@ where
self.target_nonces = Some(target_nonces);
self.strategy.best_target_nonces_updated(
TargetClientNonces {
latest_nonce: nonces.latest_nonce,
nonces_data: (),
},
TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () },
race_state,
)
}
@@ -399,14 +396,12 @@ where
}
if let Some(ref mut target_nonces) = self.target_nonces {
target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce);
target_nonces.latest_nonce =
std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce);
}
self.strategy.finalized_target_nonces_updated(
TargetClientNonces {
latest_nonce: nonces.latest_nonce,
nonces_data: (),
},
TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () },
race_state,
)
}
@@ -428,12 +423,15 @@ where
// There's additional condition in the message delivery race: target would reject messages
// if there are too much unconfirmed messages at the inbound lane.
// The receiving race is responsible to deliver confirmations back to the source chain. So if
// there's a lot of unconfirmed messages, let's wait until it'll be able to do its job.
// The receiving race is responsible to deliver confirmations back to the source chain. So
// if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job.
let latest_received_nonce_at_target = target_nonces.latest_nonce;
let confirmations_missing = latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source);
let confirmations_missing =
latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source);
match confirmations_missing {
Some(confirmations_missing) if confirmations_missing >= self.max_unconfirmed_nonces_at_target => {
Some(confirmations_missing)
if confirmations_missing >= self.max_unconfirmed_nonces_at_target =>
{
log::debug!(
target: "bridge",
"Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \
@@ -445,50 +443,55 @@ where
self.max_unconfirmed_nonces_at_target,
);
return None;
return None
}
_ => (),
}
// Ok - we may have new nonces to deliver. But target may still reject new messages, because we haven't
// notified it that (some) messages have been confirmed. So we may want to include updated
// `source.latest_confirmed` in the proof.
// Ok - we may have new nonces to deliver. But target may still reject new messages, because
// we haven't notified it that (some) messages have been confirmed. So we may want to
// include updated `source.latest_confirmed` in the proof.
//
// Important note: we're including outbound state lane proof whenever there are unconfirmed nonces
// on the target chain. Other strategy is to include it only if it's absolutely necessary.
// Important note: we're including outbound state lane proof whenever there are unconfirmed
// nonces on the target chain. Other strategy is to include it only if it's absolutely
// necessary.
let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce;
let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source;
let outbound_state_proof_required =
latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source;
// The target node would also reject messages if there are too many entries in the
// "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then
// we should wait for confirmations race.
let unrewarded_relayer_entries_limit_reached =
target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries
>= self.max_unrewarded_relayer_entries_at_target;
target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries >=
self.max_unrewarded_relayer_entries_at_target;
if unrewarded_relayer_entries_limit_reached {
// so there are already too many unrewarded relayer entries in the set
//
// => check if we can prove enough rewards. If not, we should wait for more rewards to be paid
// => check if we can prove enough rewards. If not, we should wait for more rewards to
// be paid
let number_of_rewards_being_proved =
latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target);
let enough_rewards_being_proved = number_of_rewards_being_proved
>= target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry;
let enough_rewards_being_proved = number_of_rewards_being_proved >=
target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry;
if !enough_rewards_being_proved {
return None;
return None
}
}
// If we're here, then the confirmations race did its job && sending side now knows that messages
// have been delivered. Now let's select nonces that we want to deliver.
// If we're here, then the confirmations race did its job && sending side now knows that
// messages have been delivered. Now let's select nonces that we want to deliver.
//
// We may deliver at most:
//
// max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_target)
// max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target -
// latest_confirmed_nonce_at_target)
//
// messages in the batch. But since we're including outbound state proof in the batch, then it
// may be increased to:
// messages in the batch. But since we're including outbound state proof in the batch, then
// it may be increased to:
//
// max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_source)
// max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target -
// latest_confirmed_nonce_at_source)
let future_confirmed_nonce_at_target = if outbound_state_proof_required {
latest_confirmed_nonce_at_source
} else {
@@ -505,7 +508,8 @@ where
let lane_source_client = self.lane_source_client.clone();
let lane_target_client = self.lane_target_client.clone();
let maximal_source_queue_index = self.strategy.maximal_available_source_queue_index(race_state)?;
let maximal_source_queue_index =
self.strategy.maximal_available_source_queue_index(race_state)?;
let previous_total_dispatch_weight = self.total_queued_dispatch_weight();
let source_queue = self.strategy.source_queue();
let range_end = select_nonces_for_delivery_transaction(
@@ -529,10 +533,7 @@ where
Some((
selected_nonces,
MessageProofParameters {
outbound_state_proof_required,
dispatch_weight,
},
MessageProofParameters { outbound_state_proof_required, dispatch_weight },
))
}
}
@@ -595,9 +596,9 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
// 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 <= max_messages_weight_in_single_batch => {
new_selected_weight
}
Some(new_selected_weight)
if new_selected_weight <= max_messages_weight_in_single_batch =>
new_selected_weight,
new_selected_weight if selected_count == 0 => {
log::warn!(
target: "bridge",
@@ -607,13 +608,14 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
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 selected_size.checked_add(details.size) {
Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => new_selected_size,
Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch =>
new_selected_size,
new_selected_size if selected_count == 0 => {
log::warn!(
target: "bridge",
@@ -623,14 +625,14 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
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 > max_messages_in_this_batch {
break;
break
}
// If dispatch fee has been paid at the source chain, it means that it is **relayer** who's
@@ -639,13 +641,14 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
// 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.
// So in the latter case we're not adding the dispatch weight to the delivery transaction
// weight.
let mut new_selected_prepaid_nonces = selected_prepaid_nonces;
let new_selected_unpaid_weight = match details.dispatch_fee_payment {
DispatchFeePayment::AtSourceChain => {
new_selected_prepaid_nonces += 1;
selected_unpaid_weight.saturating_add(details.dispatch_weight)
}
},
DispatchFeePayment::AtTargetChain => selected_unpaid_weight,
};
@@ -654,11 +657,12 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
match relayer_mode {
RelayerMode::Altruistic => {
soft_selected_count = index + 1;
}
},
RelayerMode::Rational => {
let delivery_transaction_cost = lane_target_client
.estimate_delivery_transaction_in_source_tokens(
hard_selected_begin_nonce..=(hard_selected_begin_nonce + index as MessageNonce),
hard_selected_begin_nonce..=
(hard_selected_begin_nonce + index as MessageNonce),
new_selected_prepaid_nonces,
new_selected_unpaid_weight,
new_selected_size as u32,
@@ -678,7 +682,8 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
let is_total_reward_less_than_cost = total_reward < total_cost;
let prev_total_cost = total_cost;
let prev_total_reward = total_reward;
total_confirmations_cost = total_confirmations_cost.saturating_add(&confirmation_transaction_cost);
total_confirmations_cost =
total_confirmations_cost.saturating_add(&confirmation_transaction_cost);
total_reward = total_reward.saturating_add(&details.reward);
total_cost = total_confirmations_cost.saturating_add(&delivery_transaction_cost);
if !is_total_reward_less_than_cost && total_reward < total_cost {
@@ -713,7 +718,7 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
selected_reward = total_reward;
selected_cost = total_cost;
}
}
},
}
hard_selected_count = index + 1;
@@ -725,9 +730,11 @@ async fn select_nonces_for_delivery_transaction<P: MessageLane>(
}
if hard_selected_count != soft_selected_count {
let hard_selected_end_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1;
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;
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 \
@@ -785,9 +792,9 @@ mod tests {
use super::*;
use crate::message_lane_loop::{
tests::{
header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, TestSourceClient,
TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, BASE_MESSAGE_DELIVERY_TRANSACTION_COST,
CONFIRMATION_TRANSACTION_COST,
header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance,
TestSourceClient, TestSourceHeaderId, TestTargetClient, TestTargetHeaderId,
BASE_MESSAGE_DELIVERY_TRANSACTION_COST, CONFIRMATION_TRANSACTION_COST,
},
MessageDetails,
};
@@ -795,13 +802,14 @@ mod tests {
const DEFAULT_DISPATCH_WEIGHT: Weight = 1;
const DEFAULT_SIZE: u32 = 1;
const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST
+ BASE_MESSAGE_DELIVERY_TRANSACTION_COST
+ DEFAULT_DISPATCH_WEIGHT
+ (DEFAULT_SIZE as TestSourceChainBalance);
const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST +
BASE_MESSAGE_DELIVERY_TRANSACTION_COST +
DEFAULT_DISPATCH_WEIGHT +
(DEFAULT_SIZE as TestSourceChainBalance);
type TestRaceState = RaceState<TestSourceHeaderId, TestTargetHeaderId, TestMessagesProof>;
type TestStrategy = MessageDeliveryStrategy<TestMessageLane, TestSourceClient, TestTargetClient>;
type TestStrategy =
MessageDeliveryStrategy<TestMessageLane, TestSourceClient, TestTargetClient>;
fn source_nonces(
new_nonces: RangeInclusive<MessageNonce>,
@@ -863,14 +871,12 @@ mod tests {
strategy: BasicStrategy::new(),
};
race_strategy
.strategy
.source_nonces_updated(header_id(1), source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain));
race_strategy.strategy.source_nonces_updated(
header_id(1),
source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain),
);
let target_nonces = TargetClientNonces {
latest_nonce: 19,
nonces_data: (),
};
let target_nonces = TargetClientNonces { latest_nonce: 19, nonces_data: () };
race_strategy
.strategy
.best_target_nonces_updated(target_nonces.clone(), &mut race_state);
@@ -890,7 +896,9 @@ mod tests {
#[test]
fn weights_map_works_as_nonces_range() {
fn build_map(range: RangeInclusive<MessageNonce>) -> MessageDetailsMap<TestSourceChainBalance> {
fn build_map(
range: RangeInclusive<MessageNonce>,
) -> MessageDetailsMap<TestSourceChainBalance> {
range
.map(|idx| {
(
@@ -937,7 +945,8 @@ mod tests {
// we need to wait until confirmations will be delivered by receiving race
strategy.latest_confirmed_nonces_at_source = vec![(
header_id(1),
strategy.target_nonces.as_ref().unwrap().latest_nonce - strategy.max_unconfirmed_nonces_at_target,
strategy.target_nonces.as_ref().unwrap().latest_nonce -
strategy.max_unconfirmed_nonces_at_target,
)]
.into_iter()
.collect();
@@ -945,13 +954,16 @@ mod tests {
}
#[async_std::test]
async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() {
async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available()
{
let (state, mut strategy) = prepare_strategy();
// if there are new confirmed nonces on source, we want to relay this information
// to target to prune rewards queue
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce =
prev_confirmed_nonce_at_source - 1;
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
Some(((20..=23), proof_parameters(true, 4)))
@@ -965,8 +977,10 @@ mod tests {
// if there are already `max_unrewarded_relayer_entries_at_target` entries at target,
// we need to wait until rewards will be paid
{
let mut unrewarded_relayers = &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers;
unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target;
let mut unrewarded_relayers =
&mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers;
unrewarded_relayers.unrewarded_relayer_entries =
strategy.max_unrewarded_relayer_entries_at_target;
unrewarded_relayers.messages_in_oldest_entry = 4;
}
assert_eq!(strategy.select_nonces_to_deliver(state).await, None);
@@ -979,12 +993,14 @@ mod tests {
// if there are already `max_unrewarded_relayer_entries_at_target` entries at target,
// we need to prove at least `messages_in_oldest_entry` rewards
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
{
let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data;
nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1;
let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers;
unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target;
unrewarded_relayers.unrewarded_relayer_entries =
strategy.max_unrewarded_relayer_entries_at_target;
unrewarded_relayers.messages_in_oldest_entry = 4;
}
assert_eq!(strategy.select_nonces_to_deliver(state).await, None);
@@ -996,12 +1012,14 @@ mod tests {
// if there are already `max_unrewarded_relayer_entries_at_target` entries at target,
// we need to prove at least `messages_in_oldest_entry` rewards
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
{
let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data;
nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3;
let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers;
unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target;
unrewarded_relayers.unrewarded_relayer_entries =
strategy.max_unrewarded_relayer_entries_at_target;
unrewarded_relayers.messages_in_oldest_entry = 3;
}
assert_eq!(
@@ -1023,15 +1041,13 @@ mod tests {
}
#[async_std::test]
async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight() {
async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight(
) {
let (state, mut strategy) = prepare_strategy();
// first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4)
strategy.strategy.source_queue_mut()[0]
.1
.get_mut(&20)
.unwrap()
.dispatch_weight = 10;
// first message doesn't fit in the batch, because it has weight (10) that overflows max
// weight (4)
strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = 10;
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
Some(((20..=20), proof_parameters(false, 10)))
@@ -1051,10 +1067,12 @@ mod tests {
}
#[async_std::test]
async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size() {
async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size(
) {
let (state, mut strategy) = prepare_strategy();
// first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4)
// first message doesn't fit in the batch, because it has weight (10) that overflows max
// weight (4)
strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().size = 10;
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
@@ -1066,7 +1084,8 @@ mod tests {
async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() {
let (state, mut strategy) = prepare_strategy();
// not all queued messages may fit in the batch, because batch has max number of messages limit
// not all queued messages may fit in the batch, because batch has max number of messages
// limit
strategy.max_messages_in_single_batch = 3;
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
@@ -1075,16 +1094,18 @@ mod tests {
}
#[async_std::test]
async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces() {
async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces(
) {
let (state, mut strategy) = prepare_strategy();
// 1 delivery confirmation from target to source is still missing, so we may only
// relay 3 new messages
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.latest_confirmed_nonces_at_source = vec![(header_id(1), prev_confirmed_nonce_at_source - 1)]
.into_iter()
.collect();
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.latest_confirmed_nonces_at_source =
vec![(header_id(1), prev_confirmed_nonce_at_source - 1)].into_iter().collect();
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce =
prev_confirmed_nonce_at_source - 1;
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
Some(((20..=22), proof_parameters(false, 3)))
@@ -1099,30 +1120,35 @@ mod tests {
//
// => so we can't deliver more than 3 messages
let (mut state, mut strategy) = prepare_strategy();
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.latest_confirmed_nonces_at_source = vec![
(header_id(1), prev_confirmed_nonce_at_source - 1),
(header_id(2), prev_confirmed_nonce_at_source),
]
.into_iter()
.collect();
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1;
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce =
prev_confirmed_nonce_at_source - 1;
state.best_finalized_source_header_id_at_best_target = Some(header_id(1));
assert_eq!(
strategy.select_nonces_to_deliver(state).await,
Some(((20..=22), proof_parameters(false, 3)))
);
// the same situation, but the header 2 is known to the target node, so we may deliver reward confirmation
// the same situation, but the header 2 is known to the target node, so we may deliver
// reward confirmation
let (mut state, mut strategy) = prepare_strategy();
let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
let prev_confirmed_nonce_at_source =
strategy.latest_confirmed_nonces_at_source.back().unwrap().1;
strategy.latest_confirmed_nonces_at_source = vec![
(header_id(1), prev_confirmed_nonce_at_source - 1),
(header_id(2), prev_confirmed_nonce_at_source),
]
.into_iter()
.collect();
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1;
strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce =
prev_confirmed_nonce_at_source - 1;
state.best_finalized_source_header_id_at_source = Some(header_id(2));
state.best_finalized_source_header_id_at_best_target = Some(header_id(2));
assert_eq!(
@@ -1136,8 +1162,9 @@ mod tests {
// let's prepare situation when:
// - all messages [20; 23] have been generated at source block#1;
let (mut state, mut strategy) = prepare_strategy();
// - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because of unrewarded
// relayers vector capacity;
//
// - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because
// of unrewarded relayers vector capacity;
strategy.max_unconfirmed_nonces_at_target = 2;
assert_eq!(
strategy.select_nonces_to_deliver(state.clone()).await,
@@ -1158,19 +1185,15 @@ mod tests {
&mut state,
);
assert_eq!(strategy.select_nonces_to_deliver(state).await, None);
//
// - messages [1; 10] receiving confirmation has been delivered at source block#2;
strategy.source_nonces_updated(
header_id(2),
SourceClientNonces {
new_nonces: MessageDetailsMap::new(),
confirmed_nonce: Some(21),
},
SourceClientNonces { new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21) },
);
//
// - so now we'll need to relay source block#11 to be able to accept messages [11; 20].
assert_eq!(
strategy.required_source_header_at_target(&header_id(1)),
Some(header_id(2))
);
assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2)));
}
#[async_std::test]
@@ -1233,8 +1256,8 @@ mod tests {
// so now we have:
// - 20..=23 with reward = cost
// - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` from the
// cost, so it should be fine;
// - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT`
// from the cost, so it should be fine;
// => when MSG#24 fee is paid at the target chain, strategy shall select all 20..=24
// => when MSG#25 fee is paid at the source chain, strategy shall only select 20..=23
strategy.select_nonces_to_deliver(state).await
@@ -1255,11 +1278,11 @@ mod tests {
// Real scenario that has happened on test deployments:
// 1) relayer witnessed M1 at block 1 => it has separate entry in the `source_queue`
// 2) relayer witnessed M2 at block 2 => it has separate entry in the `source_queue`
// 3) if block 2 is known to the target node, then both M1 and M2 are selected for single delivery,
// even though weight(M1+M2) > larger than largest allowed weight
// 3) if block 2 is known to the target node, then both M1 and M2 are selected for single
// delivery, even though weight(M1+M2) > larger than largest allowed weight
//
// This was happening because selector (`select_nonces_for_delivery_transaction`) has been called
// for every `source_queue` entry separately without preserving any context.
// This was happening because selector (`select_nonces_for_delivery_transaction`) has been
// called for every `source_queue` entry separately without preserving any context.
let (mut state, mut strategy) = prepare_strategy();
let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, AtSourceChain);
strategy.strategy.source_nonces_updated(header_id(2), nonces);
@@ -54,10 +54,12 @@ pub trait MessageRace {
}
/// State of race source client.
type SourceClientState<P> = ClientState<<P as MessageRace>::SourceHeaderId, <P as MessageRace>::TargetHeaderId>;
type SourceClientState<P> =
ClientState<<P as MessageRace>::SourceHeaderId, <P as MessageRace>::TargetHeaderId>;
/// State of race target client.
type TargetClientState<P> = ClientState<<P as MessageRace>::TargetHeaderId, <P as MessageRace>::SourceHeaderId>;
type TargetClientState<P> =
ClientState<<P as MessageRace>::TargetHeaderId, <P as MessageRace>::SourceHeaderId>;
/// Inclusive nonces range.
pub trait NoncesRange: Debug + Sized {
@@ -155,7 +157,10 @@ pub trait RaceStrategy<SourceHeaderId, TargetHeaderId, Proof>: Debug {
/// Should return true if nothing has to be synced.
fn is_empty(&self) -> bool;
/// Return id of source header that is required to be on target to continue synchronization.
fn required_source_header_at_target(&self, current_best: &SourceHeaderId) -> Option<SourceHeaderId>;
fn required_source_header_at_target(
&self,
current_best: &SourceHeaderId,
) -> Option<SourceHeaderId>;
/// Return the best nonce at source node.
///
/// `Some` is returned only if we are sure that the value is greater or equal
@@ -167,7 +172,11 @@ pub trait RaceStrategy<SourceHeaderId, TargetHeaderId, Proof>: Debug {
fn best_at_target(&self) -> Option<MessageNonce>;
/// Called when nonces are updated at source node of the race.
fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonces: SourceClientNonces<Self::SourceNoncesRange>);
fn source_nonces_updated(
&mut self,
at_block: SourceHeaderId,
nonces: SourceClientNonces<Self::SourceNoncesRange>,
);
/// Called when best nonces are updated at target node of the race.
fn best_target_nonces_updated(
&mut self,
@@ -430,8 +439,10 @@ pub async fn run<P: MessageRace, SC: SourceClient<P>, TC: TargetClient<P>>(
strategy,
);
return Err(FailedClient::Both);
} else if race_state.nonces_to_submit.is_none() && race_state.nonces_submitted.is_none() && strategy.is_empty()
return Err(FailedClient::Both)
} else if race_state.nonces_to_submit.is_none() &&
race_state.nonces_submitted.is_none() &&
strategy.is_empty()
{
stall_countdown = Instant::now();
}
@@ -439,7 +450,8 @@ pub async fn run<P: MessageRace, SC: SourceClient<P>, TC: TargetClient<P>>(
if source_client_is_online {
source_client_is_online = false;
let nonces_to_deliver = select_nonces_to_deliver(race_state.clone(), &mut strategy).await;
let nonces_to_deliver =
select_nonces_to_deliver(race_state.clone(), &mut strategy).await;
let best_at_source = strategy.best_at_source();
if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver {
@@ -451,9 +463,7 @@ pub async fn run<P: MessageRace, SC: SourceClient<P>, TC: TargetClient<P>>(
at_block,
);
source_generate_proof.set(
race_source
.generate_proof(at_block, nonces_range, proof_parameters)
.fuse(),
race_source.generate_proof(at_block, nonces_range, proof_parameters).fuse(),
);
} else if source_nonces_required && best_at_source.is_some() {
log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name());
@@ -516,7 +526,9 @@ pub async fn run<P: MessageRace, SC: SourceClient<P>, TC: TargetClient<P>>(
}
}
impl<SourceHeaderId, TargetHeaderId, Proof> Default for RaceState<SourceHeaderId, TargetHeaderId, Proof> {
impl<SourceHeaderId, TargetHeaderId, Proof> Default
for RaceState<SourceHeaderId, TargetHeaderId, Proof>
{
fn default() -> Self {
RaceState {
best_finalized_source_header_id_at_source: None,
@@ -539,7 +551,7 @@ where
let need_update = now_time.saturating_duration_since(prev_time) > Duration::from_secs(10);
if !need_update {
return prev_time;
return prev_time
}
let now_best_nonce_at_source = strategy.best_at_source();
@@ -569,11 +581,7 @@ where
.select_nonces_to_deliver(race_state)
.await
.map(|(nonces_range, proof_parameters)| {
(
best_finalized_source_header_id_at_best_target,
nonces_range,
proof_parameters,
)
(best_finalized_source_header_id_at_best_target, nonces_range, proof_parameters)
})
}
@@ -592,8 +600,14 @@ mod tests {
// target node only knows about source' BEST_AT_TARGET block
// source node has BEST_AT_SOURCE > BEST_AT_TARGET block
let mut race_state = RaceState::<_, _, ()> {
best_finalized_source_header_id_at_source: Some(HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE)),
best_finalized_source_header_id_at_best_target: Some(HeaderId(BEST_AT_TARGET, BEST_AT_TARGET)),
best_finalized_source_header_id_at_source: Some(HeaderId(
BEST_AT_SOURCE,
BEST_AT_SOURCE,
)),
best_finalized_source_header_id_at_best_target: Some(HeaderId(
BEST_AT_TARGET,
BEST_AT_TARGET,
)),
best_target_header_id: Some(HeaderId(0, 0)),
best_finalized_target_header_id: Some(HeaderId(0, 0)),
nonces_to_submit: None,
@@ -604,16 +618,10 @@ mod tests {
let mut strategy = BasicStrategy::new();
strategy.source_nonces_updated(
HeaderId(GENERATED_AT, GENERATED_AT),
SourceClientNonces {
new_nonces: 0..=10,
confirmed_nonce: None,
},
SourceClientNonces { new_nonces: 0..=10, confirmed_nonce: None },
);
strategy.best_target_nonces_updated(
TargetClientNonces {
latest_nonce: 5u64,
nonces_data: (),
},
TargetClientNonces { latest_nonce: 5u64, nonces_data: () },
&mut race_state,
);
@@ -13,16 +13,19 @@
//! Message receiving race delivers proof-of-messages-delivery from "lane.target" to "lane.source".
use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf};
use crate::message_lane_loop::{
SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient,
TargetClientState,
use crate::{
message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf},
message_lane_loop::{
SourceClient as MessageLaneSourceClient, SourceClientState,
TargetClient as MessageLaneTargetClient, TargetClientState,
},
message_race_loop::{
MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient,
TargetClientNonces,
},
message_race_strategy::BasicStrategy,
metrics::MessageLaneLoopMetrics,
};
use crate::message_race_loop::{
MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces,
};
use crate::message_race_strategy::BasicStrategy;
use crate::metrics::MessageLaneLoopMetrics;
use async_trait::async_trait;
use bp_messages::MessageNonce;
@@ -129,11 +132,7 @@ where
nonces: RangeInclusive<MessageNonce>,
_proof_parameters: Self::ProofParameters,
) -> Result<
(
TargetHeaderIdOf<P>,
RangeInclusive<MessageNonce>,
P::MessagesReceivingProof,
),
(TargetHeaderIdOf<P>, RangeInclusive<MessageNonce>, P::MessagesReceivingProof),
Self::Error,
> {
self.client
@@ -168,19 +167,14 @@ where
at_block: SourceHeaderIdOf<P>,
update_metrics: bool,
) -> Result<(SourceHeaderIdOf<P>, TargetClientNonces<()>), Self::Error> {
let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?;
let (at_block, latest_confirmed_nonce) =
self.client.latest_confirmed_received_nonce(at_block).await?;
if update_metrics {
if let Some(metrics_msg) = self.metrics_msg.as_ref() {
metrics_msg.update_source_latest_confirmed_nonce::<P>(latest_confirmed_nonce);
}
}
Ok((
at_block,
TargetClientNonces {
latest_nonce: latest_confirmed_nonce,
nonces_data: (),
},
))
Ok((at_block, TargetClientNonces { latest_nonce: latest_confirmed_nonce, nonces_data: () }))
}
async fn submit_proof(
@@ -189,9 +183,7 @@ where
nonces: RangeInclusive<MessageNonce>,
proof: P::MessagesReceivingProof,
) -> Result<RangeInclusive<MessageNonce>, Self::Error> {
self.client
.submit_messages_receiving_proof(generated_at_block, proof)
.await?;
self.client.submit_messages_receiving_proof(generated_at_block, proof).await?;
Ok(nonces)
}
}
@@ -17,7 +17,9 @@
//! 2) new nonces may be proved to target node (i.e. they have appeared at the
//! block, which is known to the target node).
use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces};
use crate::message_race_loop::{
NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces,
};
use async_trait::async_trait;
use bp_messages::MessageNonce;
@@ -40,15 +42,29 @@ pub struct BasicStrategy<
> {
/// All queued nonces.
source_queue: SourceRangesQueue<SourceHeaderHash, SourceHeaderNumber, SourceNoncesRange>,
/// The best nonce known to target node (at its best block). `None` if it has not been received yet.
/// The best nonce known to target node (at its best block). `None` if it has not been received
/// yet.
best_target_nonce: Option<MessageNonce>,
/// Unused generic types dump.
_phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>,
}
impl<SourceHeaderNumber, SourceHeaderHash, TargetHeaderNumber, TargetHeaderHash, SourceNoncesRange, Proof>
BasicStrategy<SourceHeaderNumber, SourceHeaderHash, TargetHeaderNumber, TargetHeaderHash, SourceNoncesRange, Proof>
where
impl<
SourceHeaderNumber,
SourceHeaderHash,
TargetHeaderNumber,
TargetHeaderHash,
SourceNoncesRange,
Proof,
>
BasicStrategy<
SourceHeaderNumber,
SourceHeaderHash,
TargetHeaderNumber,
TargetHeaderHash,
SourceNoncesRange,
Proof,
> where
SourceHeaderHash: Clone,
SourceHeaderNumber: Clone + Ord,
SourceNoncesRange: NoncesRange,
@@ -79,9 +95,9 @@ where
/// Returns index of the latest source queue entry, that may be delivered to the target node.
///
/// Returns `None` if no entries may be delivered. All entries before and including the `Some(_)`
/// index are guaranteed to be witnessed at source blocks that are known to be finalized at the
/// target node.
/// Returns `None` if no entries may be delivered. All entries before and including the
/// `Some(_)` index are guaranteed to be witnessed at source blocks that are known to be
/// finalized at the target node.
pub fn maximal_available_source_queue_index(
&self,
race_state: RaceState<
@@ -95,12 +111,12 @@ where
// if we have already selected nonces that we want to submit, do nothing
if race_state.nonces_to_submit.is_some() {
return None;
return None
}
// if we already submitted some nonces, do nothing
if race_state.nonces_submitted.is_some() {
return None;
return None
}
// 1) we want to deliver all nonces, starting from `target_nonce + 1`
@@ -124,17 +140,34 @@ where
while let Some((queued_at, queued_range)) = self.source_queue.pop_front() {
if let Some(range_to_requeue) = queued_range.greater_than(nonce) {
self.source_queue.push_front((queued_at, range_to_requeue));
break;
break
}
}
}
}
#[async_trait]
impl<SourceHeaderNumber, SourceHeaderHash, TargetHeaderNumber, TargetHeaderHash, SourceNoncesRange, Proof>
RaceStrategy<HeaderId<SourceHeaderHash, SourceHeaderNumber>, HeaderId<TargetHeaderHash, TargetHeaderNumber>, Proof>
for BasicStrategy<SourceHeaderNumber, SourceHeaderHash, TargetHeaderNumber, TargetHeaderHash, SourceNoncesRange, Proof>
where
impl<
SourceHeaderNumber,
SourceHeaderHash,
TargetHeaderNumber,
TargetHeaderHash,
SourceNoncesRange,
Proof,
>
RaceStrategy<
HeaderId<SourceHeaderHash, SourceHeaderNumber>,
HeaderId<TargetHeaderHash, TargetHeaderNumber>,
Proof,
>
for BasicStrategy<
SourceHeaderNumber,
SourceHeaderHash,
TargetHeaderNumber,
TargetHeaderHash,
SourceNoncesRange,
Proof,
> where
SourceHeaderHash: Clone + Debug + Send,
SourceHeaderNumber: Clone + Ord + Debug + Send,
SourceNoncesRange: NoncesRange + Debug + Send,
@@ -162,7 +195,8 @@ where
fn best_at_source(&self) -> Option<MessageNonce> {
let best_in_queue = self.source_queue.back().map(|(_, range)| range.end());
match (best_in_queue, self.best_target_nonce) {
(Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce => Some(best_in_queue),
(Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce =>
Some(best_in_queue),
(_, Some(best_target_nonce)) => Some(best_target_nonce),
(_, None) => None,
}
@@ -205,18 +239,17 @@ where
if let Some(best_target_nonce) = self.best_target_nonce {
if nonce < best_target_nonce {
return;
return
}
}
while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) {
let maybe_subrange = self
.source_queue
.pop_front()
.and_then(|(at_block, range)| range.greater_than(nonce).map(|subrange| (at_block, subrange)));
let maybe_subrange = self.source_queue.pop_front().and_then(|(at_block, range)| {
range.greater_than(nonce).map(|subrange| (at_block, subrange))
});
if let Some((at_block, subrange)) = maybe_subrange {
self.source_queue.push_front((at_block, subrange));
break;
break
}
}
@@ -238,10 +271,8 @@ where
race_state.nonces_submitted = None;
}
self.best_target_nonce = Some(std::cmp::max(
self.best_target_nonce.unwrap_or(nonces.latest_nonce),
nonce,
));
self.best_target_nonce =
Some(std::cmp::max(self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonce));
}
fn finalized_target_nonces_updated(
@@ -278,9 +309,12 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::message_lane::MessageLane;
use crate::message_lane_loop::tests::{
header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, TestSourceHeaderNumber,
use crate::{
message_lane::MessageLane,
message_lane_loop::tests::{
header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash,
TestSourceHeaderNumber,
},
};
type SourceNoncesRange = RangeInclusive<MessageNonce>;
@@ -295,17 +329,11 @@ mod tests {
>;
fn source_nonces(new_nonces: SourceNoncesRange) -> SourceClientNonces<SourceNoncesRange> {
SourceClientNonces {
new_nonces,
confirmed_nonce: None,
}
SourceClientNonces { new_nonces, confirmed_nonce: None }
}
fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces<()> {
TargetClientNonces {
latest_nonce,
nonces_data: (),
}
TargetClientNonces { latest_nonce, nonces_data: () }
}
#[test]
@@ -420,18 +448,12 @@ mod tests {
strategy.source_nonces_updated(header_id(5), source_nonces(7..=8));
state.best_finalized_source_header_id_at_best_target = Some(header_id(4));
assert_eq!(
strategy.select_nonces_to_deliver(state.clone()).await,
Some((1..=6, ()))
);
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((1..=6, ())));
strategy.best_target_nonces_updated(target_nonces(6), &mut state);
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
state.best_finalized_source_header_id_at_best_target = Some(header_id(5));
assert_eq!(
strategy.select_nonces_to_deliver(state.clone()).await,
Some((7..=8, ()))
);
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((7..=8, ())));
strategy.best_target_nonces_updated(target_nonces(8), &mut state);
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
}
@@ -471,16 +493,17 @@ mod tests {
strategy.source_nonces_updated(header_id(3), source_nonces(7..=9));
fn source_queue_nonces(
source_queue: &SourceRangesQueue<TestSourceHeaderHash, TestSourceHeaderNumber, SourceNoncesRange>,
source_queue: &SourceRangesQueue<
TestSourceHeaderHash,
TestSourceHeaderNumber,
SourceNoncesRange,
>,
) -> Vec<MessageNonce> {
source_queue.iter().flat_map(|(_, range)| range.clone()).collect()
}
strategy.remove_le_nonces_from_source_queue(1);
assert_eq!(
source_queue_nonces(&strategy.source_queue),
vec![2, 3, 4, 5, 6, 7, 8, 9],
);
assert_eq!(source_queue_nonces(&strategy.source_queue), vec![2, 3, 4, 5, 6, 7, 8, 9],);
strategy.remove_le_nonces_from_source_queue(5);
assert_eq!(source_queue_nonces(&strategy.source_queue), vec![6, 7, 8, 9],);
+20 -6
View File
@@ -16,8 +16,10 @@
//! Metrics for message lane relay loop.
use crate::message_lane::MessageLane;
use crate::message_lane_loop::{SourceClientState, TargetClientState};
use crate::{
message_lane::MessageLane,
message_lane_loop::{SourceClientState, TargetClientState},
};
use bp_messages::MessageNonce;
use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64};
@@ -81,28 +83,40 @@ impl MessageLaneLoopMetrics {
}
/// Update latest generated nonce at source.
pub fn update_source_latest_generated_nonce<P: MessageLane>(&self, source_latest_generated_nonce: MessageNonce) {
pub fn update_source_latest_generated_nonce<P: MessageLane>(
&self,
source_latest_generated_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["source_latest_generated"])
.set(source_latest_generated_nonce);
}
/// Update the latest confirmed nonce at source.
pub fn update_source_latest_confirmed_nonce<P: MessageLane>(&self, source_latest_confirmed_nonce: MessageNonce) {
pub fn update_source_latest_confirmed_nonce<P: MessageLane>(
&self,
source_latest_confirmed_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["source_latest_confirmed"])
.set(source_latest_confirmed_nonce);
}
/// Update the latest received nonce at target.
pub fn update_target_latest_received_nonce<P: MessageLane>(&self, target_latest_generated_nonce: MessageNonce) {
pub fn update_target_latest_received_nonce<P: MessageLane>(
&self,
target_latest_generated_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["target_latest_received"])
.set(target_latest_generated_nonce);
}
/// Update the latest confirmed nonce at target.
pub fn update_target_latest_confirmed_nonce<P: MessageLane>(&self, target_latest_confirmed_nonce: MessageNonce) {
pub fn update_target_latest_confirmed_nonce<P: MessageLane>(
&self,
target_latest_confirmed_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["target_latest_confirmed"])
.set(target_latest_confirmed_nonce);