TransactionInvalidationTracker (#1544)

* TransactionInvalidationTracker

* TransacitonInvalidationTracker -> TransactionTracker

* change sign_transaction method

* clippy and spelling

* removed comment

* more transactiontracker tests

* stalls_when_transaction_tracker_returns_error

* remove test code

* remove "impl TransactionTracker for ()"

* enum TrackedTransactionStatus

* test TransactionTracker in on_transaction_status

* do_wait
This commit is contained in:
Svyatoslav Nikolsky
2022-09-14 17:30:57 +03:00
committed by Bastian Köcher
parent 58fe2749d2
commit 70d6e91f20
8 changed files with 514 additions and 145 deletions
@@ -20,10 +20,10 @@
use crate::{
finality_loop::{
prune_recent_finality_proofs, read_finality_proofs_from_stream, run, run_loop_iteration,
select_better_recent_finality_proof, select_header_to_submit, FinalityLoopState,
FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient,
TargetClient,
prune_recent_finality_proofs, read_finality_proofs_from_stream, run_loop_iteration,
run_until_connection_lost, select_better_recent_finality_proof, select_header_to_submit,
FinalityLoopState, FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream,
SourceClient, TargetClient,
},
sync_loop_metrics::SyncLoopMetrics,
FinalityProof, FinalitySyncPipeline, SourceHeader,
@@ -33,7 +33,8 @@ use async_trait::async_trait;
use futures::{FutureExt, Stream, StreamExt};
use parking_lot::Mutex;
use relay_utils::{
metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError,
relay_loop::Client as RelayClient, FailedClient, HeaderId, MaybeConnectionError,
TrackedTransactionStatus, TransactionTracker,
};
use std::{
collections::HashMap,
@@ -46,6 +47,22 @@ type IsMandatory = bool;
type TestNumber = u64;
type TestHash = u64;
#[derive(Clone, Debug)]
struct TestTransactionTracker(TrackedTransactionStatus);
impl Default for TestTransactionTracker {
fn default() -> TestTransactionTracker {
TestTransactionTracker(TrackedTransactionStatus::Finalized)
}
}
#[async_trait]
impl TransactionTracker for TestTransactionTracker {
async fn wait(self) -> TrackedTransactionStatus {
self.0
}
}
#[derive(Debug, Clone)]
enum TestError {
NonConnection,
@@ -104,6 +121,7 @@ struct ClientsData {
target_best_block_id: HeaderId<TestHash, TestNumber>,
target_headers: Vec<(TestSourceHeader, TestFinalityProof)>,
target_transaction_tracker: TestTransactionTracker,
}
#[derive(Clone)]
@@ -164,6 +182,8 @@ impl RelayClient for TestTargetClient {
#[async_trait]
impl TargetClient<TestFinalitySyncPipeline> for TestTargetClient {
type TransactionTracker = TestTransactionTracker;
async fn best_finalized_source_block_id(
&self,
) -> Result<HeaderId<TestHash, TestNumber>, TestError> {
@@ -176,12 +196,13 @@ impl TargetClient<TestFinalitySyncPipeline> for TestTargetClient {
&self,
header: TestSourceHeader,
proof: TestFinalityProof,
) -> Result<(), TestError> {
) -> Result<TestTransactionTracker, TestError> {
let mut data = self.data.lock();
(self.on_method_call)(&mut data);
data.target_best_block_id = HeaderId(header.number(), header.hash());
data.target_headers.push((header, proof));
Ok(())
(self.on_method_call)(&mut data);
Ok(data.target_transaction_tracker.clone())
}
}
@@ -203,6 +224,7 @@ fn prepare_test_clients(
target_best_block_id: HeaderId(5, 5),
target_headers: vec![],
target_transaction_tracker: TestTransactionTracker(TrackedTransactionStatus::Finalized),
}));
(
TestSourceClient {
@@ -224,7 +246,7 @@ fn test_sync_params() -> FinalitySyncParams {
fn run_sync_loop(
state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static,
) -> ClientsData {
) -> (ClientsData, Result<(), FailedClient>) {
let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded();
let (source_client, target_client) = prepare_test_clients(
exit_sender,
@@ -243,21 +265,21 @@ fn run_sync_loop(
let sync_params = test_sync_params();
let clients_data = source_client.data.clone();
let _ = async_std::task::block_on(run(
let result = async_std::task::block_on(run_until_connection_lost(
source_client,
target_client,
sync_params,
MetricsParams::disabled(),
None,
exit_receiver.into_future().map(|(_, _)| ()),
));
let clients_data = clients_data.lock().clone();
clients_data
(clients_data, result)
}
#[test]
fn finality_sync_loop_works() {
let client_data = run_sync_loop(|data| {
let (client_data, result) = run_sync_loop(|data| {
// header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted,
// because header#8 has persistent finality proof && it is mandatory => it is submitted
// header#9 has persistent finality proof, but it isn't mandatory => it is submitted,
@@ -286,6 +308,7 @@ fn finality_sync_loop_works() {
data.target_best_block_id.0 == 16
});
assert_eq!(result, Ok(()));
assert_eq!(
client_data.target_headers,
vec![
@@ -538,7 +561,7 @@ fn different_forks_at_source_and_at_target_are_detected() {
progress: &mut progress,
finality_proofs_stream: &mut finality_proofs_stream,
recent_finality_proofs: &mut recent_finality_proofs,
last_transaction: None,
submitted_header_number: None,
},
&test_sync_params(),
&Some(metrics_sync.clone()),
@@ -547,3 +570,14 @@ fn different_forks_at_source_and_at_target_are_detected() {
assert!(!metrics_sync.is_using_same_fork());
}
#[test]
fn stalls_when_transaction_tracker_returns_error() {
let (_, result) = run_sync_loop(|data| {
data.target_transaction_tracker = TestTransactionTracker(TrackedTransactionStatus::Lost);
data.target_best_block_id = HeaderId(5, 5);
data.target_best_block_id.0 == 16
});
assert_eq!(result, Err(FailedClient::Both));
}