@@ -56,6 +56,11 @@ type downloadTester struct {
5656
5757// newTester creates a new downloader test mocker.
5858func newTester () * downloadTester {
59+ return newTesterWithNotification (nil )
60+ }
61+
62+ // newTester creates a new downloader test mocker.
63+ func newTesterWithNotification (success func ()) * downloadTester {
5964 freezer , err := ioutil .TempDir ("" , "" )
6065 if err != nil {
6166 panic (err )
@@ -75,7 +80,7 @@ func newTester() *downloadTester {
7580 chain : chain ,
7681 peers : make (map [string ]* downloadTesterPeer ),
7782 }
78- tester .downloader = New (0 , db , new (event.TypeMux ), tester .chain , nil , tester .dropPeer , nil )
83+ tester .downloader = New (0 , db , new (event.TypeMux ), tester .chain , nil , tester .dropPeer , success )
7984 return tester
8085}
8186
@@ -1368,3 +1373,51 @@ func testCheckpointEnforcement(t *testing.T, protocol uint, mode SyncMode) {
13681373 assertOwnChain (t , tester , len (chain .blocks ))
13691374 }
13701375}
1376+
1377+ // Tests that peers below a pre-configured checkpoint block are prevented from
1378+ // being fast-synced from, avoiding potential cheap eclipse attacks.
1379+ func TestBeaconSync66Full (t * testing.T ) { testBeaconSync (t , eth .ETH66 , FullSync ) }
1380+ func TestBeaconSync66Snap (t * testing.T ) { testBeaconSync (t , eth .ETH66 , SnapSync ) }
1381+
1382+ func testBeaconSync (t * testing.T , protocol uint , mode SyncMode ) {
1383+ //log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
1384+
1385+ var cases = []struct {
1386+ name string // The name of testing scenario
1387+ local int // The length of local chain(canonical chain assumed), 0 means genesis is the head
1388+ }{
1389+ {name : "Beacon sync since genesis" , local : 0 },
1390+ {name : "Beacon sync with short local chain" , local : 1 },
1391+ {name : "Beacon sync with long local chain" , local : blockCacheMaxItems - 15 - fsMinFullBlocks / 2 },
1392+ {name : "Beacon sync with full local chain" , local : blockCacheMaxItems - 15 - 1 },
1393+ }
1394+ for _ , c := range cases {
1395+ t .Run (c .name , func (t * testing.T ) {
1396+ success := make (chan struct {})
1397+ tester := newTesterWithNotification (func () {
1398+ close (success )
1399+ })
1400+ defer tester .terminate ()
1401+
1402+ chain := testChainBase .shorten (blockCacheMaxItems - 15 )
1403+ tester .newPeer ("peer" , protocol , chain .blocks [1 :])
1404+
1405+ // Build the local chain segment if it's required
1406+ if c .local > 0 {
1407+ tester .chain .InsertChain (chain .blocks [1 : c .local + 1 ])
1408+ }
1409+ if err := tester .downloader .BeaconSync (mode , chain .blocks [len (chain .blocks )- 1 ].Header ()); err != nil {
1410+ t .Fatalf ("Failed to beacon sync chain %v %v" , c .name , err )
1411+ }
1412+ select {
1413+ case <- success :
1414+ // Ok, downloader fully cancelled after sync cycle
1415+ if bs := int (tester .chain .CurrentBlock ().NumberU64 ()) + 1 ; bs != len (chain .blocks ) {
1416+ t .Fatalf ("synchronised blocks mismatch: have %v, want %v" , bs , len (chain .blocks ))
1417+ }
1418+ case <- time .NewTimer (time .Second * 3 ).C :
1419+ t .Fatalf ("Failed to sync chain in three seconds" )
1420+ }
1421+ })
1422+ }
1423+ }
0 commit comments