2015-12-16 05:26:23 +02:00
|
|
|
// Copyright 2015 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
2016-04-14 19:18:24 +03:00
|
|
|
|
2015-12-16 05:26:23 +02:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
crand "crypto/rand"
|
2017-04-05 01:16:29 +03:00
|
|
|
"errors"
|
2016-10-18 11:18:07 +03:00
|
|
|
"fmt"
|
2015-12-16 05:26:23 +02:00
|
|
|
"math"
|
|
|
|
"math/big"
|
|
|
|
mrand "math/rand"
|
2018-03-26 12:28:46 +03:00
|
|
|
"sync/atomic"
|
2015-12-16 05:26:23 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2022-11-14 17:41:56 +03:00
|
|
|
"github.com/ethereum/go-ethereum/common/lru"
|
2017-04-05 01:16:29 +03:00
|
|
|
"github.com/ethereum/go-ethereum/consensus"
|
2018-05-07 14:35:06 +03:00
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
2015-12-16 05:26:23 +02:00
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
2017-02-22 15:10:07 +03:00
|
|
|
"github.com/ethereum/go-ethereum/log"
|
2016-10-20 14:36:29 +03:00
|
|
|
"github.com/ethereum/go-ethereum/params"
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 19:50:58 +03:00
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
2015-12-16 05:26:23 +02:00
|
|
|
)
|
|
|
|
|
2016-04-05 16:22:04 +03:00
|
|
|
const (
|
|
|
|
headerCacheLimit = 512
|
|
|
|
tdCacheLimit = 1024
|
|
|
|
numberCacheLimit = 2048
|
|
|
|
)
|
|
|
|
|
2015-12-16 05:26:23 +02:00
|
|
|
// HeaderChain implements the basic block header chain logic that is shared by
|
|
|
|
// core.BlockChain and light.LightChain. It is not usable in itself, only as
|
|
|
|
// a part of either structure.
|
2020-01-17 13:49:32 +03:00
|
|
|
//
|
|
|
|
// HeaderChain is responsible for maintaining the header chain including the
|
|
|
|
// header query and updating.
|
|
|
|
//
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// The components maintained by headerchain includes: (1) total difficulty
|
2020-01-17 13:49:32 +03:00
|
|
|
// (2) header (3) block hash -> number mapping (4) canonical number -> hash mapping
|
|
|
|
// and (5) head header flag.
|
|
|
|
//
|
2015-12-16 05:26:23 +02:00
|
|
|
// It is not thread safe either, the encapsulating chain structures should do
|
|
|
|
// the necessary mutex locking/unlocking.
|
|
|
|
type HeaderChain struct {
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
config *params.ChainConfig
|
2015-12-16 05:26:23 +02:00
|
|
|
chainDb ethdb.Database
|
|
|
|
genesisHeader *types.Header
|
|
|
|
|
2018-02-26 12:53:10 +03:00
|
|
|
currentHeader atomic.Value // Current head of the header chain (may be above the block chain!)
|
|
|
|
currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time)
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2022-11-14 17:41:56 +03:00
|
|
|
headerCache *lru.Cache[common.Hash, *types.Header]
|
|
|
|
tdCache *lru.Cache[common.Hash, *big.Int] // most recent total difficulties
|
|
|
|
numberCache *lru.Cache[common.Hash, uint64] // most recent block numbers
|
2016-03-10 20:19:09 +02:00
|
|
|
|
|
|
|
procInterrupt func() bool
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
rand *mrand.Rand
|
|
|
|
engine consensus.Engine
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
2020-01-17 13:49:32 +03:00
|
|
|
// NewHeaderChain creates a new HeaderChain structure. ProcInterrupt points
|
|
|
|
// to the parent's interrupt semaphore.
|
2017-04-05 01:16:29 +03:00
|
|
|
func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) {
|
2015-12-16 05:26:23 +02:00
|
|
|
// Seed a fast but crypto originating random generator
|
|
|
|
seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
hc := &HeaderChain{
|
2016-03-02 00:32:43 +02:00
|
|
|
config: config,
|
2015-12-16 05:26:23 +02:00
|
|
|
chainDb: chainDb,
|
2022-11-14 17:41:56 +03:00
|
|
|
headerCache: lru.NewCache[common.Hash, *types.Header](headerCacheLimit),
|
|
|
|
tdCache: lru.NewCache[common.Hash, *big.Int](tdCacheLimit),
|
|
|
|
numberCache: lru.NewCache[common.Hash, uint64](numberCacheLimit),
|
2015-12-16 05:26:23 +02:00
|
|
|
procInterrupt: procInterrupt,
|
|
|
|
rand: mrand.New(mrand.NewSource(seed.Int64())),
|
2017-04-05 01:16:29 +03:00
|
|
|
engine: engine,
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
hc.genesisHeader = hc.GetHeaderByNumber(0)
|
|
|
|
if hc.genesisHeader == nil {
|
2017-03-02 16:03:33 +03:00
|
|
|
return nil, ErrNoGenesis
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2018-02-26 12:53:10 +03:00
|
|
|
hc.currentHeader.Store(hc.genesisHeader)
|
2018-05-07 14:35:06 +03:00
|
|
|
if head := rawdb.ReadHeadBlockHash(chainDb); head != (common.Hash{}) {
|
2016-04-05 16:22:04 +03:00
|
|
|
if chead := hc.GetHeaderByHash(head); chead != nil {
|
2018-02-26 12:53:10 +03:00
|
|
|
hc.currentHeader.Store(chead)
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 12:53:10 +03:00
|
|
|
hc.currentHeaderHash = hc.CurrentHeader().Hash()
|
2019-06-10 14:21:02 +03:00
|
|
|
headHeaderGauge.Update(hc.CurrentHeader().Number.Int64())
|
2015-12-16 05:26:23 +02:00
|
|
|
return hc, nil
|
|
|
|
}
|
|
|
|
|
2016-04-05 16:22:04 +03:00
|
|
|
// GetBlockNumber retrieves the block number belonging to the given hash
|
|
|
|
// from the cache or database
|
2018-05-07 14:35:06 +03:00
|
|
|
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
|
2016-04-05 16:22:04 +03:00
|
|
|
if cached, ok := hc.numberCache.Get(hash); ok {
|
2022-11-14 17:41:56 +03:00
|
|
|
return &cached
|
2016-04-05 16:22:04 +03:00
|
|
|
}
|
2018-05-07 14:35:06 +03:00
|
|
|
number := rawdb.ReadHeaderNumber(hc.chainDb, hash)
|
|
|
|
if number != nil {
|
|
|
|
hc.numberCache.Add(hash, *number)
|
2016-04-05 16:22:04 +03:00
|
|
|
}
|
|
|
|
return number
|
|
|
|
}
|
|
|
|
|
2020-12-09 13:13:02 +03:00
|
|
|
type headerWriteResult struct {
|
|
|
|
status WriteStatus
|
|
|
|
ignored int
|
|
|
|
imported int
|
|
|
|
lastHash common.Hash
|
|
|
|
lastHeader *types.Header
|
|
|
|
}
|
|
|
|
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// Reorg reorgs the local canonical chain into the specified chain. The reorg
|
|
|
|
// can be classified into two cases: (a) extend the local chain (b) switch the
|
|
|
|
// head to the given header.
|
|
|
|
func (hc *HeaderChain) Reorg(headers []*types.Header) error {
|
|
|
|
// Short circuit if nothing to reorg.
|
|
|
|
if len(headers) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// If the parent of the (first) block is already the canon header,
|
|
|
|
// we don't have to go backwards to delete canon blocks, but simply
|
|
|
|
// pile them onto the existing chain. Otherwise, do the necessary
|
|
|
|
// reorgs.
|
|
|
|
var (
|
|
|
|
first = headers[0]
|
|
|
|
last = headers[len(headers)-1]
|
|
|
|
batch = hc.chainDb.NewBatch()
|
|
|
|
)
|
|
|
|
if first.ParentHash != hc.currentHeaderHash {
|
|
|
|
// Delete any canonical number assignments above the new head
|
|
|
|
for i := last.Number.Uint64() + 1; ; i++ {
|
|
|
|
hash := rawdb.ReadCanonicalHash(hc.chainDb, i)
|
|
|
|
if hash == (common.Hash{}) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
rawdb.DeleteCanonicalHash(batch, i)
|
|
|
|
}
|
|
|
|
// Overwrite any stale canonical number assignments, going
|
|
|
|
// backwards from the first header in this import until the
|
|
|
|
// cross link between two chains.
|
|
|
|
var (
|
|
|
|
header = first
|
|
|
|
headNumber = header.Number.Uint64()
|
|
|
|
headHash = header.Hash()
|
|
|
|
)
|
|
|
|
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
|
|
|
|
rawdb.WriteCanonicalHash(batch, headHash, headNumber)
|
|
|
|
if headNumber == 0 {
|
|
|
|
break // It shouldn't be reached
|
|
|
|
}
|
|
|
|
headHash, headNumber = header.ParentHash, header.Number.Uint64()-1
|
|
|
|
header = hc.GetHeader(headHash, headNumber)
|
|
|
|
if header == nil {
|
|
|
|
return fmt.Errorf("missing parent %d %x", headNumber, headHash)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Extend the canonical chain with the new headers
|
|
|
|
for i := 0; i < len(headers)-1; i++ {
|
|
|
|
hash := headers[i+1].ParentHash // Save some extra hashing
|
|
|
|
num := headers[i].Number.Uint64()
|
|
|
|
rawdb.WriteCanonicalHash(batch, hash, num)
|
|
|
|
rawdb.WriteHeadHeaderHash(batch, hash)
|
|
|
|
}
|
|
|
|
// Write the last header
|
|
|
|
hash := headers[len(headers)-1].Hash()
|
|
|
|
num := headers[len(headers)-1].Number.Uint64()
|
|
|
|
rawdb.WriteCanonicalHash(batch, hash, num)
|
|
|
|
rawdb.WriteHeadHeaderHash(batch, hash)
|
|
|
|
|
|
|
|
if err := batch.Write(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Last step update all in-memory head header markers
|
|
|
|
hc.currentHeaderHash = last.Hash()
|
|
|
|
hc.currentHeader.Store(types.CopyHeader(last))
|
|
|
|
headHeaderGauge.Update(last.Number.Int64())
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteHeaders writes a chain of headers into the local chain, given that the
|
|
|
|
// parents are already known. The chain head header won't be updated in this
|
2022-05-05 10:36:26 +03:00
|
|
|
// function, the additional SetCanonical is expected in order to finish the entire
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// procedure.
|
|
|
|
func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
2020-12-09 13:13:02 +03:00
|
|
|
if len(headers) == 0 {
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
return 0, nil
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
|
|
|
ptd := hc.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
|
|
|
if ptd == nil {
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
return 0, consensus.ErrUnknownAncestor
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
2016-03-10 20:19:09 +02:00
|
|
|
var (
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
newTD = new(big.Int).Set(ptd) // Total difficulty of inserted chain
|
|
|
|
inserted []rawdb.NumberHash // Ephemeral lookup of number/hash for the chain
|
|
|
|
parentKnown = true // Set to true to force hc.HasHeader check the first iteration
|
|
|
|
batch = hc.chainDb.NewBatch()
|
2016-03-10 20:19:09 +02:00
|
|
|
)
|
2020-12-09 13:13:02 +03:00
|
|
|
for i, header := range headers {
|
|
|
|
var hash common.Hash
|
|
|
|
// The headers have already been validated at this point, so we already
|
|
|
|
// know that it's a contiguous chain, where
|
|
|
|
// headers[i].Hash() == headers[i+1].ParentHash
|
|
|
|
if i < len(headers)-1 {
|
|
|
|
hash = headers[i+1].ParentHash
|
|
|
|
} else {
|
|
|
|
hash = header.Hash()
|
|
|
|
}
|
|
|
|
number := header.Number.Uint64()
|
|
|
|
newTD.Add(newTD, header.Difficulty)
|
|
|
|
|
2021-06-25 15:53:22 +03:00
|
|
|
// If the parent was not present, store it
|
2020-12-09 13:13:02 +03:00
|
|
|
// If the header is already known, skip it, otherwise store
|
2021-06-25 15:53:22 +03:00
|
|
|
alreadyKnown := parentKnown && hc.HasHeader(hash, number)
|
|
|
|
if !alreadyKnown {
|
2020-12-09 13:13:02 +03:00
|
|
|
// Irrelevant of the canonical status, write the TD and header to the database.
|
|
|
|
rawdb.WriteTd(batch, hash, number, newTD)
|
|
|
|
hc.tdCache.Add(hash, new(big.Int).Set(newTD))
|
|
|
|
|
|
|
|
rawdb.WriteHeader(batch, header)
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
inserted = append(inserted, rawdb.NumberHash{Number: number, Hash: hash})
|
2020-12-09 13:13:02 +03:00
|
|
|
hc.headerCache.Add(hash, header)
|
|
|
|
hc.numberCache.Add(hash, number)
|
|
|
|
}
|
2021-06-25 15:53:22 +03:00
|
|
|
parentKnown = alreadyKnown
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
// Skip the slow disk write of all headers if interrupted.
|
|
|
|
if hc.procInterrupt() {
|
|
|
|
log.Debug("Premature abort during headers import")
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
return 0, errors.New("aborted")
|
2016-07-26 17:37:04 +03:00
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
// Commit to disk!
|
|
|
|
if err := batch.Write(); err != nil {
|
|
|
|
log.Crit("Failed to write headers", "error", err)
|
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
return len(inserted), nil
|
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// writeHeadersAndSetHead writes a batch of block headers and applies the last
|
|
|
|
// header as the chain head if the fork choicer says it's ok to update the chain.
|
|
|
|
// Note: This method is not concurrent-safe with inserting blocks simultaneously
|
|
|
|
// into the chain, as side effects caused by reorganisations cannot be emulated
|
|
|
|
// without the real blocks. Hence, writing headers directly should only be done
|
|
|
|
// in two scenarios: pure-header mode of operation (light clients), or properly
|
|
|
|
// separated header/block phases (non-archive clients).
|
|
|
|
func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *ForkChoice) (*headerWriteResult, error) {
|
|
|
|
inserted, err := hc.WriteHeaders(headers)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
var (
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
lastHeader = headers[len(headers)-1]
|
|
|
|
lastHash = headers[len(headers)-1].Hash()
|
|
|
|
result = &headerWriteResult{
|
|
|
|
status: NonStatTy,
|
|
|
|
ignored: len(headers) - inserted,
|
|
|
|
imported: inserted,
|
|
|
|
lastHash: lastHash,
|
|
|
|
lastHeader: lastHeader,
|
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
)
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// Ask the fork choicer if the reorg is necessary
|
|
|
|
if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else if !reorg {
|
|
|
|
if inserted != 0 {
|
|
|
|
result.status = SideStatTy
|
2020-04-22 11:27:47 +03:00
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
return result, nil
|
2020-04-22 11:27:47 +03:00
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// Special case, all the inserted headers are already on the canonical
|
|
|
|
// header chain, skip the reorg operation.
|
|
|
|
if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() {
|
|
|
|
return result, nil
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// Apply the reorg operation
|
|
|
|
if err := hc.Reorg(headers); err != nil {
|
|
|
|
return nil, err
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
result.status = CanonStatTy
|
|
|
|
return result, nil
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2017-03-22 22:44:22 +03:00
|
|
|
func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
2016-12-13 17:14:33 +03:00
|
|
|
// Do a sanity check that the provided chain is actually ordered and linked
|
|
|
|
for i := 1; i < len(chain); i++ {
|
2021-01-26 14:17:11 +03:00
|
|
|
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 {
|
|
|
|
hash := chain[i].Hash()
|
|
|
|
parentHash := chain[i-1].Hash()
|
2018-07-30 14:10:48 +03:00
|
|
|
// Chain broke ancestry, log a message (programming error) and skip insertion
|
2021-01-26 14:17:11 +03:00
|
|
|
log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", hash,
|
2020-12-09 13:13:02 +03:00
|
|
|
"parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", parentHash)
|
2016-12-13 17:14:33 +03:00
|
|
|
|
2021-04-15 20:35:00 +03:00
|
|
|
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, chain[i-1].Number,
|
2021-01-26 14:17:11 +03:00
|
|
|
parentHash.Bytes()[:4], i, chain[i].Number, hash.Bytes()[:4], chain[i].ParentHash[:4])
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
|
|
|
// If the header is a banned one, straight out abort
|
2021-01-26 14:17:11 +03:00
|
|
|
if BadHashes[chain[i].ParentHash] {
|
2021-07-29 11:17:40 +03:00
|
|
|
return i - 1, ErrBannedHash
|
2020-12-09 13:13:02 +03:00
|
|
|
}
|
|
|
|
// If it's the last header in the cunk, we need to check it too
|
|
|
|
if i == len(chain)-1 && BadHashes[chain[i].Hash()] {
|
2021-07-29 11:17:40 +03:00
|
|
|
return i, ErrBannedHash
|
2016-12-13 17:14:33 +03:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
// Generate the list of seal verification requests, and start the parallel verifier
|
|
|
|
seals := make([]bool, len(chain))
|
2019-01-24 14:18:26 +03:00
|
|
|
if checkFreq != 0 {
|
|
|
|
// In case of checkFreq == 0 all seals are left false.
|
2021-03-25 13:50:14 +03:00
|
|
|
for i := 0; i <= len(seals)/checkFreq; i++ {
|
2019-01-24 14:18:26 +03:00
|
|
|
index := i*checkFreq + hc.rand.Intn(checkFreq)
|
|
|
|
if index >= len(seals) {
|
|
|
|
index = len(seals) - 1
|
|
|
|
}
|
|
|
|
seals[index] = true
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2019-01-24 14:18:26 +03:00
|
|
|
// Last should always be verified to avoid junk.
|
|
|
|
seals[len(seals)-1] = true
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
|
|
|
|
defer close(abort)
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
// Iterate over the headers and ensure they all check out
|
2020-12-09 13:13:02 +03:00
|
|
|
for i := range chain {
|
2017-04-05 01:16:29 +03:00
|
|
|
// If the chain is terminating, stop processing blocks
|
|
|
|
if hc.procInterrupt() {
|
|
|
|
log.Debug("Premature abort during headers verification")
|
|
|
|
return 0, errors.New("aborted")
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2017-04-05 01:16:29 +03:00
|
|
|
// Otherwise wait for headers checks and ensure they pass
|
|
|
|
if err := <-results; err != nil {
|
|
|
|
return i, err
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-22 22:44:22 +03:00
|
|
|
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
// InsertHeaderChain inserts the given headers and does the reorganisations.
|
2017-05-11 04:55:48 +03:00
|
|
|
//
|
2020-12-09 13:13:02 +03:00
|
|
|
// The validity of the headers is NOT CHECKED by this method, i.e. they need to be
|
|
|
|
// validated by ValidateHeaderChain before calling InsertHeaderChain.
|
|
|
|
//
|
|
|
|
// This insert is all-or-nothing. If this returns an error, no headers were written,
|
|
|
|
// otherwise they were all processed successfully.
|
|
|
|
//
|
|
|
|
// The returned 'write status' says if the inserted headers are part of the canonical chain
|
|
|
|
// or a side chain.
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time, forker *ForkChoice) (WriteStatus, error) {
|
2020-12-09 13:13:02 +03:00
|
|
|
if hc.procInterrupt() {
|
|
|
|
return 0, errors.New("aborted")
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
all: core rework for the merge transition (#23761)
* all: work for eth1/2 transtition
* consensus/beacon, eth: change beacon difficulty to 0
* eth: updates
* all: add terminalBlockDifficulty config, fix rebasing issues
* eth: implemented merge interop spec
* internal/ethapi: update to v1.0.0.alpha.2
This commit updates the code to the new spec, moving payloadId into
it's own object. It also fixes an issue with finalizing an empty blockhash.
It also properly sets the basefee
* all: sync polishes, other fixes + refactors
* core, eth: correct semantics for LeavePoW, EnterPoS
* core: fixed rebasing artifacts
* core: light: performance improvements
* core: use keyed field (f)
* core: eth: fix compilation issues + tests
* eth/catalyst: dbetter error codes
* all: move Merger to consensus/, remove reliance on it in bc
* all: renamed EnterPoS and LeavePoW to ReachTDD and FinalizePoS
* core: make mergelogs a function
* core: use InsertChain instead of InsertBlock
* les: drop merger from lightchain object
* consensus: add merger
* core: recoverAncestors in catalyst mode
* core: fix nitpick
* all: removed merger from beacon, use TTD, nitpicks
* consensus: eth: add docstring, removed unnecessary code duplication
* consensus/beacon: better comment
* all: easy to fix nitpicks by karalabe
* consensus/beacon: verify known headers to be sure
* core: comments
* core: eth: don't drop peers who advertise blocks, nitpicks
* core: never add beacon blocks to the future queue
* core: fixed nitpicks
* consensus/beacon: simplify IsTTDReached check
* consensus/beacon: correct IsTTDReached check
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-11-26 14:23:02 +03:00
|
|
|
res, err := hc.writeHeadersAndSetHead(chain, forker)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
// Report some public statistics so the user has a clue what's going on
|
2018-09-20 11:41:59 +03:00
|
|
|
context := []interface{}{
|
2020-12-09 13:13:02 +03:00
|
|
|
"count", res.imported,
|
|
|
|
"elapsed", common.PrettyDuration(time.Since(start)),
|
2018-09-20 11:41:59 +03:00
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
if last := res.lastHeader; last != nil {
|
|
|
|
context = append(context, "number", last.Number, "hash", res.lastHash)
|
|
|
|
if timestamp := time.Unix(int64(last.Time), 0); time.Since(timestamp) > time.Minute {
|
|
|
|
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
|
|
|
}
|
2018-09-20 11:41:59 +03:00
|
|
|
}
|
2020-12-09 13:13:02 +03:00
|
|
|
if res.ignored > 0 {
|
|
|
|
context = append(context, []interface{}{"ignored", res.ignored}...)
|
2018-09-20 11:41:59 +03:00
|
|
|
}
|
|
|
|
log.Info("Imported new block headers", context...)
|
2020-12-09 13:13:02 +03:00
|
|
|
return res.status, err
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
2018-06-12 16:52:54 +03:00
|
|
|
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
|
|
|
|
// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the
|
|
|
|
// number of blocks to be individually checked before we reach the canonical chain.
|
|
|
|
//
|
|
|
|
// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.
|
|
|
|
func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) {
|
|
|
|
if ancestor > number {
|
|
|
|
return common.Hash{}, 0
|
|
|
|
}
|
|
|
|
if ancestor == 1 {
|
|
|
|
// in this case it is cheaper to just read the header
|
|
|
|
if header := hc.GetHeader(hash, number); header != nil {
|
|
|
|
return header.ParentHash, number - 1
|
|
|
|
}
|
2020-11-25 11:24:50 +03:00
|
|
|
return common.Hash{}, 0
|
2018-06-12 16:52:54 +03:00
|
|
|
}
|
|
|
|
for ancestor != 0 {
|
|
|
|
if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash {
|
2019-09-17 16:28:41 +03:00
|
|
|
ancestorHash := rawdb.ReadCanonicalHash(hc.chainDb, number-ancestor)
|
|
|
|
if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash {
|
|
|
|
number -= ancestor
|
|
|
|
return ancestorHash, number
|
|
|
|
}
|
2018-06-12 16:52:54 +03:00
|
|
|
}
|
|
|
|
if *maxNonCanonical == 0 {
|
|
|
|
return common.Hash{}, 0
|
|
|
|
}
|
|
|
|
*maxNonCanonical--
|
|
|
|
ancestor--
|
|
|
|
header := hc.GetHeader(hash, number)
|
|
|
|
if header == nil {
|
|
|
|
return common.Hash{}, 0
|
|
|
|
}
|
|
|
|
hash = header.ParentHash
|
|
|
|
number--
|
|
|
|
}
|
|
|
|
return hash, number
|
|
|
|
}
|
|
|
|
|
2015-12-16 05:26:23 +02:00
|
|
|
// GetTd retrieves a block's total difficulty in the canonical chain from the
|
2016-04-05 16:22:04 +03:00
|
|
|
// database by hash and number, caching it if found.
|
|
|
|
func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
|
2015-12-16 05:26:23 +02:00
|
|
|
// Short circuit if the td's already in the cache, retrieve otherwise
|
|
|
|
if cached, ok := hc.tdCache.Get(hash); ok {
|
2022-11-14 17:41:56 +03:00
|
|
|
return cached
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2018-05-07 14:35:06 +03:00
|
|
|
td := rawdb.ReadTd(hc.chainDb, hash, number)
|
2015-12-16 05:26:23 +02:00
|
|
|
if td == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// Cache the found body for next time and return
|
|
|
|
hc.tdCache.Add(hash, td)
|
|
|
|
return td
|
|
|
|
}
|
|
|
|
|
2016-04-05 16:22:04 +03:00
|
|
|
// GetHeader retrieves a block header from the database by hash and number,
|
|
|
|
// caching it if found.
|
|
|
|
func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
|
2015-12-16 05:26:23 +02:00
|
|
|
// Short circuit if the header's already in the cache, retrieve otherwise
|
|
|
|
if header, ok := hc.headerCache.Get(hash); ok {
|
2022-11-14 17:41:56 +03:00
|
|
|
return header
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
2018-05-07 14:35:06 +03:00
|
|
|
header := rawdb.ReadHeader(hc.chainDb, hash, number)
|
2015-12-16 05:26:23 +02:00
|
|
|
if header == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// Cache the found header for next time and return
|
2016-03-10 20:19:09 +02:00
|
|
|
hc.headerCache.Add(hash, header)
|
2015-12-16 05:26:23 +02:00
|
|
|
return header
|
|
|
|
}
|
|
|
|
|
2016-04-05 16:22:04 +03:00
|
|
|
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
|
|
|
|
// found.
|
|
|
|
func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
2018-05-07 14:35:06 +03:00
|
|
|
number := hc.GetBlockNumber(hash)
|
|
|
|
if number == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return hc.GetHeader(hash, *number)
|
2016-04-05 16:22:04 +03:00
|
|
|
}
|
|
|
|
|
2017-09-09 19:03:07 +03:00
|
|
|
// HasHeader checks if a block header is present in the database or not.
|
2020-01-17 13:49:32 +03:00
|
|
|
// In theory, if header is present in the database, all relative components
|
|
|
|
// like td and hash->number should be present too.
|
2017-09-09 19:03:07 +03:00
|
|
|
func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool {
|
|
|
|
if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) {
|
|
|
|
return true
|
|
|
|
}
|
2018-05-07 14:35:06 +03:00
|
|
|
return rawdb.HasHeader(hc.chainDb, hash, number)
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetHeaderByNumber retrieves a block header from the database by number,
|
|
|
|
// caching it (associated with its hash) if found.
|
|
|
|
func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
|
2018-05-07 14:35:06 +03:00
|
|
|
hash := rawdb.ReadCanonicalHash(hc.chainDb, number)
|
2015-12-16 05:26:23 +02:00
|
|
|
if hash == (common.Hash{}) {
|
|
|
|
return nil
|
|
|
|
}
|
2016-04-05 16:22:04 +03:00
|
|
|
return hc.GetHeader(hash, number)
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 19:50:58 +03:00
|
|
|
// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going
|
|
|
|
// backwards from the given number.
|
|
|
|
// If the 'number' is higher than the highest local header, this method will
|
|
|
|
// return a best-effort response, containing the headers that we do have.
|
|
|
|
func (hc *HeaderChain) GetHeadersFrom(number, count uint64) []rlp.RawValue {
|
|
|
|
// If the request is for future headers, we still return the portion of
|
|
|
|
// headers that we are able to serve
|
|
|
|
if current := hc.CurrentHeader().Number.Uint64(); current < number {
|
|
|
|
if count > number-current {
|
|
|
|
count -= number - current
|
|
|
|
number = current
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var headers []rlp.RawValue
|
|
|
|
// If we have some of the headers in cache already, use that before going to db.
|
|
|
|
hash := rawdb.ReadCanonicalHash(hc.chainDb, number)
|
|
|
|
if hash == (common.Hash{}) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
for count > 0 {
|
|
|
|
header, ok := hc.headerCache.Get(hash)
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
2022-11-14 17:41:56 +03:00
|
|
|
rlpData, _ := rlp.EncodeToBytes(header)
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 19:50:58 +03:00
|
|
|
headers = append(headers, rlpData)
|
2022-11-14 17:41:56 +03:00
|
|
|
hash = header.ParentHash
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 19:50:58 +03:00
|
|
|
count--
|
|
|
|
number--
|
|
|
|
}
|
|
|
|
// Read remaining from db
|
|
|
|
if count > 0 {
|
|
|
|
headers = append(headers, rawdb.ReadHeaderRange(hc.chainDb, number, count)...)
|
|
|
|
}
|
|
|
|
return headers
|
|
|
|
}
|
|
|
|
|
2019-09-26 11:47:31 +03:00
|
|
|
func (hc *HeaderChain) GetCanonicalHash(number uint64) common.Hash {
|
|
|
|
return rawdb.ReadCanonicalHash(hc.chainDb, number)
|
|
|
|
}
|
|
|
|
|
2015-12-16 05:26:23 +02:00
|
|
|
// CurrentHeader retrieves the current head header of the canonical chain. The
|
|
|
|
// header is retrieved from the HeaderChain's internal cache.
|
|
|
|
func (hc *HeaderChain) CurrentHeader() *types.Header {
|
2018-02-26 12:53:10 +03:00
|
|
|
return hc.currentHeader.Load().(*types.Header)
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
2020-01-17 13:49:32 +03:00
|
|
|
// SetCurrentHeader sets the in-memory head header marker of the canonical chan
|
|
|
|
// as the given header.
|
2015-12-16 05:26:23 +02:00
|
|
|
func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
|
2018-02-26 12:53:10 +03:00
|
|
|
hc.currentHeader.Store(head)
|
2016-03-10 20:19:09 +02:00
|
|
|
hc.currentHeaderHash = head.Hash()
|
2019-06-10 14:21:02 +03:00
|
|
|
headHeaderGauge.Update(head.Number.Int64())
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
type (
|
|
|
|
// UpdateHeadBlocksCallback is a callback function that is called by SetHead
|
2020-08-20 13:01:24 +03:00
|
|
|
// before head header is updated. The method will return the actual block it
|
|
|
|
// updated the head to (missing state) and a flag if setHead should continue
|
|
|
|
// rewinding till that forcefully (exceeded ancient limits)
|
2022-12-16 15:06:22 +03:00
|
|
|
UpdateHeadBlocksCallback func(ethdb.KeyValueWriter, *types.Header) (*types.Header, bool)
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
|
|
|
|
// DeleteBlockContentCallback is a callback function that is called by SetHead
|
|
|
|
// before each header is deleted.
|
|
|
|
DeleteBlockContentCallback func(ethdb.KeyValueWriter, common.Hash, uint64)
|
|
|
|
)
|
2015-12-16 05:26:23 +02:00
|
|
|
|
|
|
|
// SetHead rewinds the local chain to a new head. Everything above the new head
|
|
|
|
// will be deleted and the new one set.
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) {
|
2022-12-16 15:06:22 +03:00
|
|
|
hc.setHead(head, 0, updateFn, delFn)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetHeadWithTimestamp rewinds the local chain to a new head timestamp. Everything
|
|
|
|
// above the new head will be deleted and the new one set.
|
|
|
|
func (hc *HeaderChain) SetHeadWithTimestamp(time uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) {
|
|
|
|
hc.setHead(0, time, updateFn, delFn)
|
|
|
|
}
|
|
|
|
|
|
|
|
// setHead rewinds the local chain to a new head block or a head timestamp.
|
|
|
|
// Everything above the new head will be deleted and the new one set.
|
|
|
|
func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) {
|
2023-01-06 16:07:38 +03:00
|
|
|
// Sanity check that there's no attempt to undo the genesis block. This is
|
|
|
|
// a fairly synthetic case where someone enables a timestamp based fork
|
|
|
|
// below the genesis timestamp. It's nice to not allow that instead of the
|
|
|
|
// entire chain getting deleted.
|
|
|
|
if headTime > 0 && hc.genesisHeader.Time > headTime {
|
|
|
|
// Note, a critical error is quite brutal, but we should really not reach
|
|
|
|
// this point. Since pre-timestamp based forks it was impossible to have
|
|
|
|
// a fork before block 0, the setHead would always work. With timestamp
|
|
|
|
// forks it becomes possible to specify below the genesis. That said, the
|
|
|
|
// only time we setHead via timestamp is with chain config changes on the
|
|
|
|
// startup, so failing hard there is ok.
|
|
|
|
log.Crit("Rejecting genesis rewind via timestamp", "target", headTime, "genesis", hc.genesisHeader.Time)
|
|
|
|
}
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
var (
|
|
|
|
parentHash common.Hash
|
|
|
|
batch = hc.chainDb.NewBatch()
|
2020-08-20 13:01:24 +03:00
|
|
|
origin = true
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
)
|
2022-12-16 15:06:22 +03:00
|
|
|
done := func(header *types.Header) bool {
|
2023-01-03 14:06:32 +03:00
|
|
|
if headTime > 0 {
|
|
|
|
return header.Time <= headTime
|
2022-12-16 15:06:22 +03:00
|
|
|
}
|
2023-01-03 14:06:32 +03:00
|
|
|
return header.Number.Uint64() <= headBlock
|
2022-12-16 15:06:22 +03:00
|
|
|
}
|
|
|
|
for hdr := hc.CurrentHeader(); hdr != nil && !done(hdr); hdr = hc.CurrentHeader() {
|
2020-08-20 13:01:24 +03:00
|
|
|
num := hdr.Number.Uint64()
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
|
2022-12-16 15:06:22 +03:00
|
|
|
// Rewind chain to new head
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
parent := hc.GetHeader(hdr.ParentHash, num-1)
|
|
|
|
if parent == nil {
|
|
|
|
parent = hc.genesisHeader
|
|
|
|
}
|
2021-07-06 10:32:26 +03:00
|
|
|
parentHash = parent.Hash()
|
2020-08-20 13:01:24 +03:00
|
|
|
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
// Notably, since geth has the possibility for setting the head to a low
|
|
|
|
// height which is even lower than ancient head.
|
|
|
|
// In order to ensure that the head is always no higher than the data in
|
2020-08-20 13:01:24 +03:00
|
|
|
// the database (ancient store or active store), we need to update head
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
// first then remove the relative data from the database.
|
|
|
|
//
|
|
|
|
// Update head first(head fast block, head full block) before deleting the data.
|
2020-01-17 13:49:32 +03:00
|
|
|
markerBatch := hc.chainDb.NewBatch()
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
if updateFn != nil {
|
2020-08-20 13:01:24 +03:00
|
|
|
newHead, force := updateFn(markerBatch, parent)
|
2022-12-16 15:06:22 +03:00
|
|
|
if force && ((headTime > 0 && newHead.Time < headTime) || (headTime == 0 && newHead.Number.Uint64() < headBlock)) {
|
|
|
|
log.Warn("Force rewinding till ancient limit", "head", newHead.Number.Uint64())
|
2023-01-03 14:06:32 +03:00
|
|
|
headBlock, headTime = newHead.Number.Uint64(), 0 // Target timestamp passed, continue rewind in block mode (cleaner)
|
2020-08-20 13:01:24 +03:00
|
|
|
}
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
}
|
|
|
|
// Update head header then.
|
2020-01-17 13:49:32 +03:00
|
|
|
rawdb.WriteHeadHeaderHash(markerBatch, parentHash)
|
|
|
|
if err := markerBatch.Write(); err != nil {
|
|
|
|
log.Crit("Failed to update chain markers", "error", err)
|
|
|
|
}
|
|
|
|
hc.currentHeader.Store(parent)
|
|
|
|
hc.currentHeaderHash = parentHash
|
|
|
|
headHeaderGauge.Update(parent.Number.Int64())
|
all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
2019-04-25 17:59:48 +03:00
|
|
|
|
2020-08-20 13:01:24 +03:00
|
|
|
// If this is the first iteration, wipe any leftover data upwards too so
|
|
|
|
// we don't end up with dangling daps in the database
|
|
|
|
var nums []uint64
|
|
|
|
if origin {
|
|
|
|
for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ {
|
|
|
|
nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path
|
|
|
|
}
|
|
|
|
origin = false
|
|
|
|
}
|
|
|
|
nums = append(nums, num)
|
|
|
|
|
|
|
|
// Remove the related data from the database on all sidechains
|
|
|
|
for _, num := range nums {
|
|
|
|
// Gather all the side fork hashes
|
|
|
|
hashes := rawdb.ReadAllHashes(hc.chainDb, num)
|
|
|
|
if len(hashes) == 0 {
|
|
|
|
// No hashes in the database whatsoever, probably frozen already
|
|
|
|
hashes = append(hashes, hdr.Hash())
|
|
|
|
}
|
|
|
|
for _, hash := range hashes {
|
|
|
|
if delFn != nil {
|
|
|
|
delFn(batch, hash, num)
|
|
|
|
}
|
|
|
|
rawdb.DeleteHeader(batch, hash, num)
|
|
|
|
rawdb.DeleteTd(batch, hash, num)
|
|
|
|
}
|
|
|
|
rawdb.DeleteCanonicalHash(batch, num)
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
}
|
2020-01-17 13:49:32 +03:00
|
|
|
// Flush all accumulated deletions.
|
|
|
|
if err := batch.Write(); err != nil {
|
|
|
|
log.Crit("Failed to rewind block", "error", err)
|
|
|
|
}
|
2015-12-16 05:26:23 +02:00
|
|
|
// Clear out any stale content from the caches
|
|
|
|
hc.headerCache.Purge()
|
|
|
|
hc.tdCache.Purge()
|
2016-04-05 16:22:04 +03:00
|
|
|
hc.numberCache.Purge()
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetGenesis sets a new genesis block header for the chain
|
|
|
|
func (hc *HeaderChain) SetGenesis(head *types.Header) {
|
|
|
|
hc.genesisHeader = head
|
|
|
|
}
|
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
// Config retrieves the header chain's chain configuration.
|
|
|
|
func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config }
|
2015-12-16 05:26:23 +02:00
|
|
|
|
2017-04-12 16:38:31 +03:00
|
|
|
// Engine retrieves the header chain's consensus engine.
|
|
|
|
func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine }
|
|
|
|
|
2017-04-05 01:16:29 +03:00
|
|
|
// GetBlock implements consensus.ChainReader, and returns nil for every input as
|
|
|
|
// a header chain does not have blocks available for retrieval.
|
|
|
|
func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
|
|
|
return nil
|
2015-12-16 05:26:23 +02:00
|
|
|
}
|