diff --git a/eth/downloader/beaconsync.go b/eth/downloader/beaconsync.go index 8088f16af9..3ce78b046c 100644 --- a/eth/downloader/beaconsync.go +++ b/eth/downloader/beaconsync.go @@ -201,8 +201,6 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) { chainHead = d.blockchain.CurrentBlock() case SnapSync: chainHead = d.blockchain.CurrentSnapBlock() - default: - chainHead = d.lightchain.CurrentHeader() } number := chainHead.Number.Uint64() @@ -256,8 +254,6 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) { known = d.blockchain.HasBlock(h.Hash(), n) case SnapSync: known = d.blockchain.HasFastBlock(h.Hash(), n) - default: - known = d.lightchain.HasHeader(h.Hash(), n) } if !known { end = check diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index bb083260e4..a5f310a84a 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -98,7 +98,6 @@ type Downloader struct { syncStatsChainHeight uint64 // Highest block number known when syncing started syncStatsLock sync.RWMutex // Lock protecting the sync stats fields - lightchain LightChain blockchain BlockChain // Callbacks @@ -143,8 +142,8 @@ type Downloader struct { syncLogTime time.Time // Time instance when status was last reported } -// LightChain encapsulates functions required to synchronise a light chain. -type LightChain interface { +// BlockChain encapsulates functions required to sync a (full or snap) blockchain. +type BlockChain interface { // HasHeader verifies a header's presence in the local chain. HasHeader(common.Hash, uint64) bool @@ -162,11 +161,6 @@ type LightChain interface { // SetHead rewinds the local chain to a new head. SetHead(uint64) error -} - -// BlockChain encapsulates functions required to sync a (full or snap) blockchain. -type BlockChain interface { - LightChain // HasBlock verifies a block's presence in the local chain. HasBlock(common.Hash, uint64) bool @@ -201,17 +195,13 @@ type BlockChain interface { } // New creates a new downloader to fetch hashes and blocks from remote peers. -func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, success func()) *Downloader { - if lightchain == nil { - lightchain = chain - } +func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, dropPeer peerDropFn, success func()) *Downloader { dl := &Downloader{ stateDB: stateDb, mux: mux, queue: newQueue(blockCacheMaxItems, blockCacheInitialItems), peers: newPeerSet(), blockchain: chain, - lightchain: lightchain, dropPeer: dropPeer, headerProcCh: make(chan *headerTask, 1), quitCh: make(chan struct{}), @@ -245,10 +235,8 @@ func (d *Downloader) Progress() ethereum.SyncProgress { current = d.blockchain.CurrentBlock().Number.Uint64() case d.blockchain != nil && mode == SnapSync: current = d.blockchain.CurrentSnapBlock().Number.Uint64() - case d.lightchain != nil: - current = d.lightchain.CurrentHeader().Number.Uint64() default: - log.Error("Unknown downloader chain/mode combo", "light", d.lightchain != nil, "full", d.blockchain != nil, "mode", mode) + log.Error("Unknown downloader chain/mode combo", "full", d.blockchain != nil, "mode", mode) } progress, pending := d.SnapSyncer.Progress() @@ -402,7 +390,7 @@ func (d *Downloader) syncToHead() (err error) { if err != nil { d.mux.Post(FailedEvent{err}) } else { - latest := d.lightchain.CurrentHeader() + latest := d.blockchain.CurrentHeader() d.mux.Post(DoneEvent{latest}) } }() @@ -520,7 +508,7 @@ func (d *Downloader) syncToHead() (err error) { } // Rewind the ancient store and blockchain if reorg happens. if origin+1 < frozen { - if err := d.lightchain.SetHead(origin); err != nil { + if err := d.blockchain.SetHead(origin); err != nil { return err } log.Info("Truncated excess ancient chain segment", "oldhead", frozen-1, "newhead", origin) @@ -690,34 +678,32 @@ func (d *Downloader) processHeaders(origin uint64) error { chunkHashes := hashes[:limit] // In case of header only syncing, validate the chunk immediately - if mode == SnapSync || mode == LightSync { + if mode == SnapSync { // Although the received headers might be all valid, a legacy // PoW/PoA sync must not accept post-merge headers. Make sure // that any transition is rejected at this point. if len(chunkHeaders) > 0 { - if n, err := d.lightchain.InsertHeaderChain(chunkHeaders); err != nil { + if n, err := d.blockchain.InsertHeaderChain(chunkHeaders); err != nil { log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err) return fmt.Errorf("%w: %v", errInvalidChain, err) } } } - // Unless we're doing light chains, schedule the headers for associated content retrieval - if mode == FullSync || mode == SnapSync { - // If we've reached the allowed number of pending headers, stall a bit - for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { - timer.Reset(time.Second) - select { - case <-d.cancelCh: - return errCanceled - case <-timer.C: - } - } - // Otherwise insert the headers for content retrieval - inserts := d.queue.Schedule(chunkHeaders, chunkHashes, origin) - if len(inserts) != len(chunkHeaders) { - return fmt.Errorf("%w: stale headers", errBadPeer) + // If we've reached the allowed number of pending headers, stall a bit + for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { + timer.Reset(time.Second) + select { + case <-d.cancelCh: + return errCanceled + case <-timer.C: } } + // Otherwise insert the headers for content retrieval + inserts := d.queue.Schedule(chunkHeaders, chunkHashes, origin) + if len(inserts) != len(chunkHeaders) { + return fmt.Errorf("%w: stale headers", errBadPeer) + } + headers = headers[limit:] hashes = hashes[limit:] origin += uint64(limit) @@ -1056,7 +1042,7 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea headers []*types.Header ) for { - parent := d.lightchain.GetHeaderByHash(current.ParentHash) + parent := d.blockchain.GetHeaderByHash(current.ParentHash) if parent == nil { break // The chain is not continuous, or the chain is exhausted } diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 92403277fd..cb6c27c68a 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -80,7 +80,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester { chain: chain, peers: make(map[string]*downloadTesterPeer), } - tester.downloader = New(db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, success) + tester.downloader = New(db, new(event.TypeMux), tester.chain, tester.dropPeer, success) return tester } @@ -390,9 +390,6 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) { t.Helper() headers, blocks, receipts := length, length, length - if tester.downloader.getMode() == LightSync { - blocks, receipts = 1, 1 - } if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers { t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers) } @@ -404,9 +401,8 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) { } } -func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) } -func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) } -func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) } +func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) } +func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) } func testCanonSync(t *testing.T, protocol uint, mode SyncMode) { success := make(chan struct{}) @@ -511,9 +507,8 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) { } // Tests that a canceled download wipes all previously accumulated state. -func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) } -func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) } -func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) } +func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) } +func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) } func testCancel(t *testing.T, protocol uint, mode SyncMode) { complete := make(chan struct{}) @@ -544,9 +539,8 @@ func testCancel(t *testing.T, protocol uint, mode SyncMode) { // Tests that synchronisations behave well in multi-version protocol environments // and not wreak havoc on other nodes in the network. -func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) } -func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) } -func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) } +func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) } +func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) } func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) { complete := make(chan struct{}) @@ -584,9 +578,8 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) { // Tests that if a block is empty (e.g. header only), no body request should be // made, and instead the header should be assembled into a whole block in itself. -func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) } -func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) } -func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) } +func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) } +func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) } func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) { success := make(chan struct{}) @@ -625,7 +618,7 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) { // Validate the number of block bodies that should have been requested bodiesNeeded, receiptsNeeded := 0, 0 for _, block := range chain.blocks[1:] { - if mode != LightSync && (len(block.Transactions()) > 0 || len(block.Uncles()) > 0) { + if len(block.Transactions()) > 0 || len(block.Uncles()) > 0 { bodiesNeeded++ } } @@ -700,9 +693,8 @@ func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) { // Tests that synchronisation progress (origin block number, current block number // and highest block number) is tracked and updated correctly. -func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) } -func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) } -func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) } +func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) } +func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) } func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) { success := make(chan struct{}) @@ -740,17 +732,7 @@ func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) { if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil { t.Fatalf("failed to beacon-sync chain: %v", err) } - var startingBlock uint64 - if mode == LightSync { - // in light-sync mode: - // * the starting block is 0 on the second sync cycle because blocks - // are never downloaded. - // * The current/highest blocks reported in the progress reflect the - // current/highest header. - startingBlock = 0 - } else { - startingBlock = uint64(len(chain.blocks)/2 - 1) - } + startingBlock := uint64(len(chain.blocks)/2 - 1) select { case <-success: diff --git a/eth/downloader/modes.go b/eth/downloader/modes.go index d388b9ee4d..7de908849e 100644 --- a/eth/downloader/modes.go +++ b/eth/downloader/modes.go @@ -29,7 +29,7 @@ const ( ) func (mode SyncMode) IsValid() bool { - return mode >= FullSync && mode <= LightSync + return mode >= FullSync && mode < LightSync } // String implements the stringer interface. diff --git a/eth/handler.go b/eth/handler.go index 143ac2a8a5..d5117584c0 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -180,7 +180,7 @@ func newHandler(config *handlerConfig) (*handler, error) { return nil, errors.New("snap sync not supported with snapshots disabled") } // Construct the downloader (long sync) - h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, h.enableSyncedFeatures) + h.downloader = downloader.New(config.Database, h.eventMux, h.chain, h.removePeer, h.enableSyncedFeatures) fetchTx := func(peer string, hashes []common.Hash) error { p := h.peers.peer(peer)