mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 04:01:02 +00:00
Squashed 'bridges/' changes from 23dda62482..407bf44a8a
407bf44a8a add missing license header (#1204) 9babb19810 Custom relay strategy (#1198) c287872a11 fix clippy things (#1200) 3a40e62789 Expose some const value and type (#1186) 32b61476d1 increase sleep before connectingMillau (#1195) aabe7041fa revert messages transactions mortality (#1194) 3651f4f909 Message transactions mortality (#1191) 364d6e155d Bump dependencies (#1180) f0389acc08 cargo +nightly fmt --all (#1192) b270b6a016 Unify error enums in substrate and ethereum clients with `thiserror` (#1094) 58c4946f74 Limit max call size of Rialto/Millau runtimes (#1187) fd56a8cd56 Add UI to the deployment (#1047) 16f01dc736 Westend -> Millau alerts are pending before notifications are sent (#1184) 5628c11ece replace collective flip with babe randomness in Rialto (#1188) 1094a63b00 ignore another (pretty bad) RUSTSEC (#1185) 379fe323ea fix/ignore cargo deny issues (#1183) 92af5e6e64 additional log in finality relay + rephrase "failed" (#1182) b996a3b681 Rialto parachain in test deployments (#1178) 28d9332b44 Resubmit transactions strategy for Polkadot/Kusama (#1175) d0172c6847 Playing with CI (#1179) fb6f42456d fix checks order when registering parachain (#1177) ee828c005a Register-parachain subcommand of substrate-relay (#1170) 8cd2b1a112 Token swap pallet benchmarks (#1174) bb811accb1 fix collision with westend bridge (#1172) 8d2fba70ed add token swaps to test deployments (#1169) b6d1bdfe2c publish rialto parachain collator image (#1171) 834ae4a10a Fix OutboundLaneData types (#1159) 5ee0ea1626 copypasted -> copied (#1168) c3bb835f18 fix spelling (#1167) f90d041dc9 Upgrade `jsonrpsee` to v0.3 (#1051) 598c9b6d0d add some basic tests for swap tokens (#1164) 05e88c61f5 publish images when tag of specific format(e.g. v2021-09-27 + v2021-09-27-1) is published (#1166) 7f3f94a6e0 Fix CI again (#1165) ff37de332f Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153) 36fbba839b fix clippy warning (#1163) 16da44d018 explicit wasm build (#1158) c9c8226449 Match substrate's fmt (#1148) 2fdd7f3e5e Fix/ignore clippy warnings (#1157) 43dfcc2686 Adding LookupAddress (#1156) 951eaa5582 Add rialto-parachain runtime and node (#1142) 803d266d61 Rename MessageId -> BridgeMessageId (#1152) 5f234484fc Box large arguments of GRANDPA pallet (#1154) cf9abc1011 Fix spelling (#1150) ab83ba2e58 Relay subcommand that performs token RLT <> MLAU token swap (#1141) 832536caf0 Polkadot <> Kusama relayers (#1122) 6d0daa8975 Add `OnMessageAccepted` callback (#1134) 5d03a20b3e Integrate token swap pallet into Millau runtime (#1099) ea4cfa833e Adding MultiAddress type and ValidationCodeHash (#1139) c20325a784 Add tests for `Raw` and `BridgeSendMessage` enum `Call` variants (#1125) 6d802416e2 increase pause before pining Rialto nodes (#1137) b54fa56b62 calculate fee using full message payload (#1132) ca5d8178f5 Add parachain pallets to rialto runtime (#1053) 9eaae4142e fix transaction resubmitter limits for Millau -> Rialto transactions (#1135) 9d4e17783c add --mandatory-headers-only cli option to complex relay (#1129) 1c5e0ec1cb Add local CI info to README (#1131) a8e0929e14 chore: spellchecker fixes (#1130) 3b8e2118e3 set fee for importing mandatory headers to zero (#1127) 49bba9aa52 another bunch of words for spellchecker (#1128) 8a72eafef6 Increase pause before messages generation start (#1126) 1f0ba9a191 Move some associated types from relay_substrate_client::Chain to bp_runtime::Chain (#1087) 74bc1a5b54 Transactions resubmitter (#1083) 21ba001f26 log max balance drop when sending message (#1117) 638a7ddffa Code Cleaning (#1124) be6555c51b Fix buildah logout (#1120) 87539c4a98 Format code work (#1116) 526fe7fdd7 fix spelling (#1119) bd4ce7f241 Fix spelling (#1118) 3c1147858e added missing constants to Kusama/Polkadot primitives (#1114) 52093b22ab Fix delivery transaction estimation used by rational relayer (#1109) 77a2f2fbed Remove fund account checks from upgrade. (#1111) 824334802b Rename param and update comment (#1108) d7784bfe06 Fix spellcheck (#1110) 0b18f5906a Refactor substrate messages source and substrate messages target (#1105) b27240bbff fix compilation (#1107) 9697da4fe8 Emit mortal transactions from relay (#1073) b29396c077 Change vault vars type to env vars (#1084) 35e0bbdc0c Make clippy mandatory. (#1103) a517e8541f Remove unused deps (#1102) 873dae608a Remove unnessary deps (#1101) 13450b74ee Stored conversion rate updater (#1005) 74389829f3 [BREAKING] Migrate messages pallet to frame v2 (#1088) 424da938dd README fix (#1100) 865744c909 upgrade currency exchange pallet to frame v2 (#1097) b5038148b3 Add missing docs (#1095) 0791e911c1 Common crate for substrate-relay (#1082) 3834c9d880 Update high-level-overview.md (#1093) c93553face Increase the time window for messaging alerts. (#1092) 8b9cc3cecd migrate pallet-shift-session-manager to frame v2 (#1090) dc91813c22 migrate eth PoA pallet to frame v2 (#1091) f16bb098cc Migrate dispatch pallet to frame v2 (#1089) 19f4325348 Bridge/This Chain Ids should be exposed as constants on pallet level. (#1085) 6381122df7 Change ChainSpec::from_genesis for Rialto and Millau chains to reflect the chain names. (#1079) 0f1d33e973 Make CI happy again (#1086) 238e65d96f fix typo (#1080) fc008457b6 Token-swap-over-bridge pallet (#944) 3fb97fa5ef Fix full spellcheck (#1076) eae4ed7170 fixed wrong trace (#1075) 219a0fad04 merge two weight-related loops in messages pallet (#1071) fc85632fdb increase_message_fee depends on stored mesage size (#1066) 530f37a23b companion for https://github.com/paritytech/polkadot/pull/3507 (#1067) 53b8cba683 sc_basic_authorship=trace for millau nodes (#1074) 9874e05e98 Improve traces of message generator scripts (#1069) 7b5ee84fbb extract message_details impl into runtime common (#1070) 5a4aed5a8b refund weight for mot pruning messages (#1062) 90e3d1e111 Fix Westend -> Millau sync (#1064) 427d30ddfc When restarting client, also "restart" tokio runtime (#1065) d47c05eeef Change get pipeline sensitive variables from Vault instead of GitLab settings (#1063) d775a85415 use tokio reactor to execute jsonrpsee futures (#1061) 15c8cd61cb Use BABE to author blocks on Rialto (previously: Aura) (#1050) 5186293500 Allow reading suri && password override from file (#1059) b506298262 Update jsonrpsee reference (#1049) 1734d00517 enable weight fee adjustent in Rialto/Millau (#1044) 607265afae Pay dispatch fee at target chain cli option (#1043) ce79ef91be bump dependencies before start referencing polkadot repo (#1048) 924fa24f6d Cli option for greedy relayer + run no-losses relayer by default (#1042) e21eba7b59 Yrong README Fixup + M1 Fixes (#1045) 20d08204a2 Confirm delivery detects when more than expected messages are confirmed (#1039) 994b846b52 pre and post dispatch weights of OnDeliveryConfirmed callback (#1040) 1dd5297e84 give real value to Rialto and Millau tokens (#1038) 035bee8715 Use real conversion rate in greedy relayer strategy (#1035) 9cfaecd0f7 fixed metrics prefix (#1037) 1d8d224937 Use kebab-case for bridge arguments (#1036) f30a4c79a6 Shared reference to conversion rate metric value (#1034) c34d7a5cbb estimate transaction fee (#1015) 93404b18bb change alert period from 2m to 10m for Westend -> Millau (GRANDPA or public node itself is lagging sometimes) (#1032) git-subtree-dir: bridges git-subtree-split: 407bf44a8a5f4e60aceef2dc755cd9ff09929ac3
This commit is contained in:
@@ -1,494 +0,0 @@
|
||||
// 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.
|
||||
|
||||
//! Basic delivery strategy. The strategy selects nonces if:
|
||||
//!
|
||||
//! 1) there are more nonces on the source side than on the target side;
|
||||
//! 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 async_trait::async_trait;
|
||||
use bp_messages::MessageNonce;
|
||||
use relay_utils::HeaderId;
|
||||
use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive};
|
||||
|
||||
/// Queue of nonces known to the source node.
|
||||
pub type SourceRangesQueue<SourceHeaderHash, SourceHeaderNumber, SourceNoncesRange> =
|
||||
VecDeque<(HeaderId<SourceHeaderHash, SourceHeaderNumber>, SourceNoncesRange)>;
|
||||
|
||||
/// Nonces delivery strategy.
|
||||
#[derive(Debug)]
|
||||
pub struct BasicStrategy<
|
||||
SourceHeaderNumber,
|
||||
SourceHeaderHash,
|
||||
TargetHeaderNumber,
|
||||
TargetHeaderHash,
|
||||
SourceNoncesRange,
|
||||
Proof,
|
||||
> {
|
||||
/// All queued nonces.
|
||||
source_queue: SourceRangesQueue<SourceHeaderHash, SourceHeaderNumber, SourceNoncesRange>,
|
||||
/// 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
|
||||
SourceHeaderHash: Clone,
|
||||
SourceHeaderNumber: Clone + Ord,
|
||||
SourceNoncesRange: NoncesRange,
|
||||
{
|
||||
/// Create new delivery strategy.
|
||||
pub fn new() -> Self {
|
||||
BasicStrategy {
|
||||
source_queue: VecDeque::new(),
|
||||
best_target_nonce: None,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reference to source queue.
|
||||
pub(crate) fn source_queue(
|
||||
&self,
|
||||
) -> &VecDeque<(HeaderId<SourceHeaderHash, SourceHeaderNumber>, SourceNoncesRange)> {
|
||||
&self.source_queue
|
||||
}
|
||||
|
||||
/// Mutable reference to source queue to use in tests.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn source_queue_mut(
|
||||
&mut self,
|
||||
) -> &mut VecDeque<(HeaderId<SourceHeaderHash, SourceHeaderNumber>, SourceNoncesRange)> {
|
||||
&mut self.source_queue
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn maximal_available_source_queue_index(
|
||||
&self,
|
||||
race_state: RaceState<
|
||||
HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
HeaderId<TargetHeaderHash, TargetHeaderNumber>,
|
||||
Proof,
|
||||
>,
|
||||
) -> Option<usize> {
|
||||
// if we do not know best nonce at target node, we can't select anything
|
||||
let _ = self.best_target_nonce?;
|
||||
|
||||
// if we have already selected nonces that we want to submit, do nothing
|
||||
if race_state.nonces_to_submit.is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// if we already submitted some nonces, do nothing
|
||||
if race_state.nonces_submitted.is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// 1) we want to deliver all nonces, starting from `target_nonce + 1`
|
||||
// 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized
|
||||
// by target client
|
||||
// 3) selector is used for more complicated logic
|
||||
//
|
||||
// => let's first select range of entries inside deque that are already finalized at
|
||||
// the target client and pass this range to the selector
|
||||
let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target?;
|
||||
self.source_queue
|
||||
.iter()
|
||||
.enumerate()
|
||||
.take_while(|(_, (queued_at, _))| queued_at.0 <= best_header_at_target.0)
|
||||
.map(|(index, _)| index)
|
||||
.last()
|
||||
}
|
||||
|
||||
/// Remove all nonces that are less than or equal to given nonce from the source queue.
|
||||
pub fn remove_le_nonces_from_source_queue(&mut self, nonce: MessageNonce) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
SourceHeaderHash: Clone + Debug + Send,
|
||||
SourceHeaderNumber: Clone + Ord + Debug + Send,
|
||||
SourceNoncesRange: NoncesRange + Debug + Send,
|
||||
TargetHeaderHash: Debug + Send,
|
||||
TargetHeaderNumber: Debug + Send,
|
||||
Proof: Debug + Send,
|
||||
{
|
||||
type SourceNoncesRange = SourceNoncesRange;
|
||||
type ProofParameters = ();
|
||||
type TargetNoncesData = ();
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.source_queue.is_empty()
|
||||
}
|
||||
|
||||
fn required_source_header_at_target(
|
||||
&self,
|
||||
current_best: &HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
) -> Option<HeaderId<SourceHeaderHash, SourceHeaderNumber>> {
|
||||
self.source_queue
|
||||
.back()
|
||||
.and_then(|(h, _)| if h.0 > current_best.0 { Some(h.clone()) } else { None })
|
||||
}
|
||||
|
||||
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_target_nonce)) => Some(best_target_nonce),
|
||||
(_, None) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn best_at_target(&self) -> Option<MessageNonce> {
|
||||
self.best_target_nonce
|
||||
}
|
||||
|
||||
fn source_nonces_updated(
|
||||
&mut self,
|
||||
at_block: HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
nonces: SourceClientNonces<SourceNoncesRange>,
|
||||
) {
|
||||
let best_in_queue = self
|
||||
.source_queue
|
||||
.back()
|
||||
.map(|(_, range)| range.end())
|
||||
.or(self.best_target_nonce)
|
||||
.unwrap_or_default();
|
||||
self.source_queue.extend(
|
||||
nonces
|
||||
.new_nonces
|
||||
.greater_than(best_in_queue)
|
||||
.into_iter()
|
||||
.map(move |range| (at_block.clone(), range)),
|
||||
)
|
||||
}
|
||||
|
||||
fn best_target_nonces_updated(
|
||||
&mut self,
|
||||
nonces: TargetClientNonces<()>,
|
||||
race_state: &mut RaceState<
|
||||
HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
HeaderId<TargetHeaderHash, TargetHeaderNumber>,
|
||||
Proof,
|
||||
>,
|
||||
) {
|
||||
let nonce = nonces.latest_nonce;
|
||||
|
||||
if let Some(best_target_nonce) = self.best_target_nonce {
|
||||
if nonce < best_target_nonce {
|
||||
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)));
|
||||
if let Some((at_block, subrange)) = maybe_subrange {
|
||||
self.source_queue.push_front((at_block, subrange));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let need_to_select_new_nonces = race_state
|
||||
.nonces_to_submit
|
||||
.as_ref()
|
||||
.map(|(_, nonces, _)| *nonces.end() <= nonce)
|
||||
.unwrap_or(false);
|
||||
if need_to_select_new_nonces {
|
||||
race_state.nonces_to_submit = None;
|
||||
}
|
||||
|
||||
let need_new_nonces_to_submit = race_state
|
||||
.nonces_submitted
|
||||
.as_ref()
|
||||
.map(|nonces| *nonces.end() <= nonce)
|
||||
.unwrap_or(false);
|
||||
if need_new_nonces_to_submit {
|
||||
race_state.nonces_submitted = None;
|
||||
}
|
||||
|
||||
self.best_target_nonce = Some(std::cmp::max(
|
||||
self.best_target_nonce.unwrap_or(nonces.latest_nonce),
|
||||
nonce,
|
||||
));
|
||||
}
|
||||
|
||||
fn finalized_target_nonces_updated(
|
||||
&mut self,
|
||||
nonces: TargetClientNonces<()>,
|
||||
_race_state: &mut RaceState<
|
||||
HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
HeaderId<TargetHeaderHash, TargetHeaderNumber>,
|
||||
Proof,
|
||||
>,
|
||||
) {
|
||||
self.best_target_nonce = Some(std::cmp::max(
|
||||
self.best_target_nonce.unwrap_or(nonces.latest_nonce),
|
||||
nonces.latest_nonce,
|
||||
));
|
||||
}
|
||||
|
||||
async fn select_nonces_to_deliver(
|
||||
&mut self,
|
||||
race_state: RaceState<
|
||||
HeaderId<SourceHeaderHash, SourceHeaderNumber>,
|
||||
HeaderId<TargetHeaderHash, TargetHeaderNumber>,
|
||||
Proof,
|
||||
>,
|
||||
) -> Option<(RangeInclusive<MessageNonce>, Self::ProofParameters)> {
|
||||
let maximal_source_queue_index = self.maximal_available_source_queue_index(race_state)?;
|
||||
let range_begin = self.source_queue[0].1.begin();
|
||||
let range_end = self.source_queue[maximal_source_queue_index].1.end();
|
||||
self.remove_le_nonces_from_source_queue(range_end);
|
||||
Some((range_begin..=range_end, ()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::message_lane::MessageLane;
|
||||
use crate::message_lane_loop::tests::{
|
||||
header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, TestSourceHeaderNumber,
|
||||
};
|
||||
|
||||
type SourceNoncesRange = RangeInclusive<MessageNonce>;
|
||||
|
||||
type BasicStrategy<P> = super::BasicStrategy<
|
||||
<P as MessageLane>::SourceHeaderNumber,
|
||||
<P as MessageLane>::SourceHeaderHash,
|
||||
<P as MessageLane>::TargetHeaderNumber,
|
||||
<P as MessageLane>::TargetHeaderHash,
|
||||
SourceNoncesRange,
|
||||
<P as MessageLane>::MessagesProof,
|
||||
>;
|
||||
|
||||
fn source_nonces(new_nonces: SourceNoncesRange) -> SourceClientNonces<SourceNoncesRange> {
|
||||
SourceClientNonces {
|
||||
new_nonces,
|
||||
confirmed_nonce: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces<()> {
|
||||
TargetClientNonces {
|
||||
latest_nonce,
|
||||
nonces_data: (),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strategy_is_empty_works() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
assert!(strategy.is_empty());
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=1));
|
||||
assert!(!strategy.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn best_at_source_is_never_lower_than_target_nonce() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
assert_eq!(strategy.best_at_source(), None);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=5));
|
||||
assert_eq!(strategy.best_at_source(), None);
|
||||
strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default());
|
||||
assert_eq!(strategy.source_queue, vec![]);
|
||||
assert_eq!(strategy.best_at_source(), Some(10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn source_nonce_is_never_lower_than_known_target_nonce() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default());
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=5));
|
||||
assert_eq!(strategy.source_queue, vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn source_nonce_is_never_lower_than_latest_known_source_nonce() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=5));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(1..=3));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(1..=5));
|
||||
assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_nonce_is_never_lower_than_latest_known_target_nonce() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
assert_eq!(strategy.best_target_nonce, None);
|
||||
strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default());
|
||||
assert_eq!(strategy.best_target_nonce, Some(10));
|
||||
strategy.best_target_nonces_updated(target_nonces(5), &mut Default::default());
|
||||
assert_eq!(strategy.best_target_nonce, Some(10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updated_target_nonce_removes_queued_entries() {
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=5));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(6..=10));
|
||||
strategy.source_nonces_updated(header_id(3), source_nonces(11..=15));
|
||||
strategy.source_nonces_updated(header_id(4), source_nonces(16..=20));
|
||||
strategy.best_target_nonces_updated(target_nonces(15), &mut Default::default());
|
||||
assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]);
|
||||
strategy.best_target_nonces_updated(target_nonces(17), &mut Default::default());
|
||||
assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_nonces_are_dropped_on_target_nonce_update() {
|
||||
let mut state = RaceState::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None)));
|
||||
strategy.best_target_nonces_updated(target_nonces(7), &mut state);
|
||||
assert!(state.nonces_to_submit.is_some());
|
||||
strategy.best_target_nonces_updated(target_nonces(10), &mut state);
|
||||
assert!(state.nonces_to_submit.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submitted_nonces_are_dropped_on_target_nonce_update() {
|
||||
let mut state = RaceState::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
state.nonces_submitted = Some(5..=10);
|
||||
strategy.best_target_nonces_updated(target_nonces(7), &mut state);
|
||||
assert!(state.nonces_submitted.is_some());
|
||||
strategy.best_target_nonces_updated(target_nonces(10), &mut state);
|
||||
assert!(state.nonces_submitted.is_none());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn nothing_is_selected_if_something_is_already_selected() {
|
||||
let mut state = RaceState::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None)));
|
||||
strategy.best_target_nonces_updated(target_nonces(0), &mut state);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=10));
|
||||
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn nothing_is_selected_if_something_is_already_submitted() {
|
||||
let mut state = RaceState::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
state.nonces_submitted = Some(1..=10);
|
||||
strategy.best_target_nonces_updated(target_nonces(0), &mut state);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=10));
|
||||
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn select_nonces_to_deliver_works() {
|
||||
let mut state = RaceState::<_, _, TestMessagesProof>::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.best_target_nonces_updated(target_nonces(0), &mut state);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=1));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(2..=2));
|
||||
strategy.source_nonces_updated(header_id(3), source_nonces(3..=6));
|
||||
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, ()))
|
||||
);
|
||||
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, ()))
|
||||
);
|
||||
strategy.best_target_nonces_updated(target_nonces(8), &mut state);
|
||||
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maximal_available_source_queue_index_works() {
|
||||
let mut state = RaceState::<_, _, TestMessagesProof>::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.best_target_nonces_updated(target_nonces(0), &mut state);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=3));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(4..=6));
|
||||
strategy.source_nonces_updated(header_id(3), source_nonces(7..=9));
|
||||
|
||||
state.best_finalized_source_header_id_at_best_target = Some(header_id(0));
|
||||
assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), None);
|
||||
|
||||
state.best_finalized_source_header_id_at_best_target = Some(header_id(1));
|
||||
assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(0));
|
||||
|
||||
state.best_finalized_source_header_id_at_best_target = Some(header_id(2));
|
||||
assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(1));
|
||||
|
||||
state.best_finalized_source_header_id_at_best_target = Some(header_id(3));
|
||||
assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(2));
|
||||
|
||||
state.best_finalized_source_header_id_at_best_target = Some(header_id(4));
|
||||
assert_eq!(strategy.maximal_available_source_queue_index(state), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_le_nonces_from_source_queue_works() {
|
||||
let mut state = RaceState::<_, _, TestMessagesProof>::default();
|
||||
let mut strategy = BasicStrategy::<TestMessageLane>::new();
|
||||
strategy.best_target_nonces_updated(target_nonces(0), &mut state);
|
||||
strategy.source_nonces_updated(header_id(1), source_nonces(1..=3));
|
||||
strategy.source_nonces_updated(header_id(2), source_nonces(4..=6));
|
||||
strategy.source_nonces_updated(header_id(3), source_nonces(7..=9));
|
||||
|
||||
fn source_queue_nonces(
|
||||
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],
|
||||
);
|
||||
|
||||
strategy.remove_le_nonces_from_source_queue(5);
|
||||
assert_eq!(source_queue_nonces(&strategy.source_queue), vec![6, 7, 8, 9],);
|
||||
|
||||
strategy.remove_le_nonces_from_source_queue(9);
|
||||
assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::<MessageNonce>::new(),);
|
||||
|
||||
strategy.remove_le_nonces_from_source_queue(100);
|
||||
assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::<MessageNonce>::new(),);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user