@@ -139,10 +139,6 @@ func (dl *downloadTester) sync(id string, td *big.Int) error {
139
139
if hashes + blocks == 0 && atomic .LoadInt32 (& dl .downloader .processing ) == 0 {
140
140
break
141
141
}
142
- // If there are queued blocks, but the head is missing, it's a stale leftover
143
- if hashes + blocks > 0 && atomic .LoadInt32 (& dl .downloader .processing ) == 0 && dl .downloader .queue .GetHeadBlock () == nil {
144
- break
145
- }
146
142
// Otherwise sleep a bit and retry
147
143
time .Sleep (time .Millisecond )
148
144
}
@@ -660,6 +656,67 @@ func testEmptyBlockShortCircuit(t *testing.T, protocol int) {
660
656
}
661
657
}
662
658
659
+ // Tests that headers are enqueued continuously, preventing malicious nodes from
660
+ // stalling the downloader by feeding gapped header chains.
661
+ func TestMissingHeaderAttack62 (t * testing.T ) { testMissingHeaderAttack (t , 62 ) }
662
+ func TestMissingHeaderAttack63 (t * testing.T ) { testMissingHeaderAttack (t , 63 ) }
663
+ func TestMissingHeaderAttack64 (t * testing.T ) { testMissingHeaderAttack (t , 64 ) }
664
+
665
+ func testMissingHeaderAttack (t * testing.T , protocol int ) {
666
+ // Create a small enough block chain to download
667
+ targetBlocks := blockCacheLimit - 15
668
+ hashes , blocks := makeChain (targetBlocks , 0 , genesis )
669
+
670
+ tester := newTester ()
671
+
672
+ // Attempt a full sync with an attacker feeding gapped headers
673
+ tester .newPeer ("attack" , protocol , hashes , blocks )
674
+ missing := targetBlocks / 2
675
+ delete (tester .peerBlocks ["attack" ], hashes [missing ])
676
+
677
+ if err := tester .sync ("attack" , nil ); err == nil {
678
+ t .Fatalf ("succeeded attacker synchronisation" )
679
+ }
680
+ // Synchronise with the valid peer and make sure sync succeeds
681
+ tester .newPeer ("valid" , protocol , hashes , blocks )
682
+ if err := tester .sync ("valid" , nil ); err != nil {
683
+ t .Fatalf ("failed to synchronise blocks: %v" , err )
684
+ }
685
+ if imported := len (tester .ownBlocks ); imported != len (hashes ) {
686
+ t .Fatalf ("synchronised block mismatch: have %v, want %v" , imported , len (hashes ))
687
+ }
688
+ }
689
+
690
+ // Tests that if requested headers are shifted (i.e. first is missing), the queue
691
+ // detects the invalid numbering.
692
+ func TestShiftedHeaderAttack62 (t * testing.T ) { testShiftedHeaderAttack (t , 62 ) }
693
+ func TestShiftedHeaderAttack63 (t * testing.T ) { testShiftedHeaderAttack (t , 63 ) }
694
+ func TestShiftedHeaderAttack64 (t * testing.T ) { testShiftedHeaderAttack (t , 64 ) }
695
+
696
+ func testShiftedHeaderAttack (t * testing.T , protocol int ) {
697
+ // Create a small enough block chain to download
698
+ targetBlocks := blockCacheLimit - 15
699
+ hashes , blocks := makeChain (targetBlocks , 0 , genesis )
700
+
701
+ tester := newTester ()
702
+
703
+ // Attempt a full sync with an attacker feeding shifted headers
704
+ tester .newPeer ("attack" , protocol , hashes , blocks )
705
+ delete (tester .peerBlocks ["attack" ], hashes [len (hashes )- 2 ])
706
+
707
+ if err := tester .sync ("attack" , nil ); err == nil {
708
+ t .Fatalf ("succeeded attacker synchronisation" )
709
+ }
710
+ // Synchronise with the valid peer and make sure sync succeeds
711
+ tester .newPeer ("valid" , protocol , hashes , blocks )
712
+ if err := tester .sync ("valid" , nil ); err != nil {
713
+ t .Fatalf ("failed to synchronise blocks: %v" , err )
714
+ }
715
+ if imported := len (tester .ownBlocks ); imported != len (hashes ) {
716
+ t .Fatalf ("synchronised block mismatch: have %v, want %v" , imported , len (hashes ))
717
+ }
718
+ }
719
+
663
720
// Tests that if a peer sends an invalid body for a requested block, it gets
664
721
// dropped immediately by the downloader.
665
722
func TestInvalidBlockBodyAttack62 (t * testing.T ) { testInvalidBlockBodyAttack (t , 62 ) }
0 commit comments