@@ -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
@@ -1462,3 +1467,51 @@ func testCheckpointEnforcement(t *testing.T, protocol uint, mode SyncMode) {
14621467 assertOwnChain (t , tester , len (chain .blocks ))
14631468 }
14641469}
1470+
1471+ // Tests that peers below a pre-configured checkpoint block are prevented from
1472+ // being fast-synced from, avoiding potential cheap eclipse attacks.
1473+ func TestBeaconSync66Full (t * testing.T ) { testBeaconSync (t , eth .ETH66 , FullSync ) }
1474+ func TestBeaconSync66Snap (t * testing.T ) { testBeaconSync (t , eth .ETH66 , SnapSync ) }
1475+
1476+ func testBeaconSync (t * testing.T , protocol uint , mode SyncMode ) {
1477+ //log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
1478+
1479+ var cases = []struct {
1480+ name string // The name of testing scenario
1481+ local int // The length of local chain(canonical chain assumed), 0 means genesis is the head
1482+ }{
1483+ {name : "Beacon sync since genesis" , local : 0 },
1484+ {name : "Beacon sync with short local chain" , local : 1 },
1485+ {name : "Beacon sync with long local chain" , local : blockCacheMaxItems - 15 - fsMinFullBlocks / 2 },
1486+ {name : "Beacon sync with full local chain" , local : blockCacheMaxItems - 15 - 1 },
1487+ }
1488+ for _ , c := range cases {
1489+ t .Run (c .name , func (t * testing.T ) {
1490+ success := make (chan struct {})
1491+ tester := newTesterWithNotification (func () {
1492+ close (success )
1493+ })
1494+ defer tester .terminate ()
1495+
1496+ chain := testChainBase .shorten (blockCacheMaxItems - 15 )
1497+ tester .newPeer ("peer" , protocol , chain .blocks [1 :])
1498+
1499+ // Build the local chain segment if it's required
1500+ if c .local > 0 {
1501+ tester .chain .InsertChain (chain .blocks [1 : c .local + 1 ])
1502+ }
1503+ if err := tester .downloader .BeaconSync (mode , chain .blocks [len (chain .blocks )- 1 ].Header ()); err != nil {
1504+ t .Fatalf ("Failed to beacon sync chain %v %v" , c .name , err )
1505+ }
1506+ select {
1507+ case <- success :
1508+ // Ok, downloader fully cancelled after sync cycle
1509+ if bs := int (tester .chain .CurrentBlock ().NumberU64 ()) + 1 ; bs != len (chain .blocks ) {
1510+ t .Fatalf ("synchronised blocks mismatch: have %v, want %v" , bs , len (chain .blocks ))
1511+ }
1512+ case <- time .NewTimer (time .Second * 3 ).C :
1513+ t .Fatalf ("Failed to sync chain in three seconds" )
1514+ }
1515+ })
1516+ }
1517+ }
0 commit comments