Skip to content

Commit c02904c

Browse files
authored
fix(node): Allow syncing from header-sub as soon as node is connected (#324)
1 parent 0060ec5 commit c02904c

File tree

1 file changed

+50
-31
lines changed

1 file changed

+50
-31
lines changed

node/src/syncer.rs

+50-31
Original file line numberDiff line numberDiff line change
@@ -571,11 +571,8 @@ where
571571
let network_head = p2p.get_head_header().await?;
572572
let network_head_height = network_head.height().value();
573573

574-
// If store is empty, intialize it with network head
575-
if store.head_height().await.is_err() {
576-
store.insert(network_head.clone()).await?;
577-
}
578-
574+
// Insert HEAD to the store and initialize header-sub
575+
store.insert(network_head.clone()).await?;
579576
p2p.init_header_sub(network_head).await?;
580577

581578
Ok(network_head_height)
@@ -795,7 +792,7 @@ mod tests {
795792
let store = Arc::new(store);
796793

797794
let mut headers = gen.next_many(520);
798-
let network_head = headers.last().cloned().unwrap();
795+
let network_head = gen.next(); // height 546
799796

800797
let syncer = Syncer::start(SyncerArgs {
801798
p2p: Arc::new(p2p),
@@ -816,9 +813,9 @@ mod tests {
816813
let head_from_syncer = p2p_mock.expect_init_header_sub().await;
817814
assert_eq!(head_from_syncer, network_head);
818815

819-
assert_syncing(&syncer, &store, &[1..=25], 545).await;
816+
assert_syncing(&syncer, &store, &[1..=25, 546..=546], 546).await;
820817

821-
// Syncer requested the first batch ([37, 545])
818+
// Syncer requested the first batch ([34, 545])
822819
handle_session_batch(
823820
&mut p2p_mock,
824821
&headers,
@@ -834,7 +831,7 @@ mod tests {
834831
],
835832
)
836833
.await;
837-
assert_syncing(&syncer, &store, &[1..=25, 34..=545], 545).await;
834+
assert_syncing(&syncer, &store, &[1..=25, 34..=546], 546).await;
838835

839836
// Syncer requested the remaining batch ([26, 33])
840837
let (height, amount, respond_to) = p2p_mock.expect_header_request_for_height_cmd().await;
@@ -844,7 +841,7 @@ mod tests {
844841
.send(Ok(headers.drain(..8).collect()))
845842
.map_err(|_| "headers [538, 545]")
846843
.unwrap();
847-
assert_syncing(&syncer, &store, &[1..=545], 545).await;
844+
assert_syncing(&syncer, &store, &[1..=546], 546).await;
848845

849846
// Syncer is fulling synced and awaiting for events
850847
p2p_mock.expect_no_cmd().await;
@@ -872,45 +869,64 @@ mod tests {
872869
#[async_test]
873870
async fn all_peers_disconnected() {
874871
let mut gen = ExtendedHeaderGenerator::new();
875-
let headers = gen.next_many(26);
876872

877-
// Start Syncer and report height 25 as HEAD
878-
let (syncer, store, mut p2p_mock) = initialized_syncer(headers[25].clone()).await;
873+
let _gap = gen.next_many(24);
874+
let header25 = gen.next();
875+
let _gap = gen.next_many(4);
876+
let header30 = gen.next();
877+
let _gap = gen.next_many(4);
878+
let header35 = gen.next();
879+
880+
// Start Syncer and report height 30 as HEAD
881+
let (syncer, store, mut p2p_mock) = initialized_syncer(header30).await;
879882

880-
// Wait for the request but do not reply to it
883+
// Wait for the request but do not reply to it.
881884
let (height, amount, _respond_to) = p2p_mock.expect_header_request_for_height_cmd().await;
882885
assert_eq!(height, 1);
883-
assert_eq!(amount, 25);
886+
assert_eq!(amount, 29);
884887

885888
p2p_mock.announce_all_peers_disconnected();
889+
// Syncer is now back to `connecting_event_loop`.
886890
p2p_mock.expect_no_cmd().await;
887891

892+
// Accounce a non-trusted peer. Syncer in `connecting_event_loop` can progress only
893+
// if a trusted peer is connected.
894+
p2p_mock.announce_peer_connected();
895+
p2p_mock.expect_no_cmd().await;
896+
897+
// Accounce a trusted peer.
888898
p2p_mock.announce_trusted_peer_connected();
889899

890-
// Syncer is now back to `connecting_event_loop`, so we expect a request for HEAD
900+
// Now syncer will send request for HEAD.
891901
let (height, amount, respond_to) = p2p_mock.expect_header_request_for_height_cmd().await;
892902
assert_eq!(height, 0);
893903
assert_eq!(amount, 1);
894-
// Now HEAD is height 26
895-
respond_to.send(Ok(vec![headers[25].clone()])).unwrap();
896904

897-
// Syncer initializes HeaderSub with the latest HEAD
898-
let head_from_syncer = p2p_mock.expect_init_header_sub().await;
899-
assert_eq!(&head_from_syncer, headers.last().unwrap());
905+
// Report an older head. Syncer should not accept it.
906+
respond_to.send(Ok(vec![header25])).unwrap();
907+
assert_syncing(&syncer, &store, &[30..=30], 30).await;
900908

901-
// Syncer now moved to `connected_event_loop`
909+
// Syncer will request HEAD again after some time.
910+
sleep(Duration::from_secs(1)).await;
902911
let (height, amount, respond_to) = p2p_mock.expect_header_request_for_height_cmd().await;
903-
assert_eq!(height, 1);
904-
assert_eq!(amount, 25);
905-
respond_to
906-
.send(Ok(headers[0..25].to_vec()))
907-
// Mapping to avoid spamming error message on failure
908-
.map_err(|_| "headers [1, 26]")
909-
.unwrap();
912+
assert_eq!(height, 0);
913+
assert_eq!(amount, 1);
910914

911-
assert_syncing(&syncer, &store, &[1..=26], 26).await;
915+
// Report newer HEAD than before.
916+
respond_to.send(Ok(vec![header35.clone()])).unwrap();
917+
assert_syncing(&syncer, &store, &[30..=30, 35..=35], 35).await;
912918

913-
// Node is fully synced, so nothing else is produced.
919+
// Syncer initializes HeaderSub with the latest HEAD.
920+
let head_from_syncer = p2p_mock.expect_init_header_sub().await;
921+
assert_eq!(head_from_syncer, header35);
922+
923+
// Syncer now is in `connected_event_loop` and will try to sync the gap
924+
// that is closer to HEAD.
925+
let (height, amount, _respond_to) = p2p_mock.expect_header_request_for_height_cmd().await;
926+
assert_eq!(height, 31);
927+
assert_eq!(amount, 4);
928+
929+
p2p_mock.announce_all_peers_disconnected();
914930
p2p_mock.expect_no_cmd().await;
915931
}
916932

@@ -1039,6 +1055,9 @@ mod tests {
10391055
let head_from_syncer = handle.expect_init_header_sub().await;
10401056
assert_eq!(head_from_syncer, head);
10411057

1058+
let head_height = head.height().value();
1059+
assert_syncing(&syncer, &store, &[head_height..=head_height], head_height).await;
1060+
10421061
(syncer, store, handle)
10431062
}
10441063

0 commit comments

Comments
 (0)