Skip to content

Commit 93f456d

Browse files
committed
Merge go-ethereum v1.15.11 (#602)
2 parents 1dc8f2e + 36b2371 commit 93f456d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5042
-295
lines changed

beacon/engine/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ type executionPayloadEnvelopeMarshaling struct {
154154

155155
type PayloadStatusV1 struct {
156156
Status string `json:"status"`
157-
Witness *hexutil.Bytes `json:"witness"`
157+
Witness *hexutil.Bytes `json:"witness,omitempty"`
158158
LatestValidHash *common.Hash `json:"latestValidHash"`
159159
ValidationError *string `json:"validationError"`
160160
}

cmd/devp2p/internal/ethtest/suite.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func (s *Suite) EthTests() []utesting.Test {
7070
{Name: "Status", Fn: s.TestStatus},
7171
// get block headers
7272
{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
73+
{Name: "GetNonexistentBlockHeaders", Fn: s.TestGetNonexistentBlockHeaders},
7374
{Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
7475
{Name: "SameRequestID", Fn: s.TestSameRequestID},
7576
{Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
@@ -158,6 +159,48 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
158159
}
159160
}
160161

162+
func (s *Suite) TestGetNonexistentBlockHeaders(t *utesting.T) {
163+
t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value)
164+
to check if the node disconnects after receiving multiple invalid requests.`)
165+
166+
conn, err := s.dial()
167+
if err != nil {
168+
t.Fatalf("dial failed: %v", err)
169+
}
170+
defer conn.Close()
171+
172+
if err := conn.peer(s.chain, nil); err != nil {
173+
t.Fatalf("peering failed: %v", err)
174+
}
175+
176+
// Create request with max uint64 value for a nonexistent block
177+
badReq := &eth.GetBlockHeadersPacket{
178+
GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
179+
Origin: eth.HashOrNumber{Number: ^uint64(0)},
180+
Amount: 1,
181+
Skip: 0,
182+
Reverse: false,
183+
},
184+
}
185+
186+
// Send request 10 times. Some clients are lient on the first few invalids.
187+
for i := 0; i < 10; i++ {
188+
badReq.RequestId = uint64(i)
189+
if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, badReq); err != nil {
190+
if err == errDisc {
191+
t.Fatalf("peer disconnected after %d requests", i+1)
192+
}
193+
t.Fatalf("write failed: %v", err)
194+
}
195+
}
196+
197+
// Check if peer disconnects at the end.
198+
code, _, err := conn.Read()
199+
if err == errDisc || code == discMsg {
200+
t.Fatal("peer improperly disconnected")
201+
}
202+
}
203+
161204
func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
162205
t.Log(`This test requests blocks headers from the node, performing two requests
163206
concurrently, with different request IDs.`)

cmd/geth/chaincmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,13 @@ func initGenesis(ctx *cli.Context) error {
246246
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
247247
defer triedb.Close()
248248

249-
_, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
249+
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
250250
if err != nil {
251251
utils.Fatalf("Failed to write genesis block: %v", err)
252252
}
253+
if compatErr != nil {
254+
utils.Fatalf("Failed to write chain config: %v", compatErr)
255+
}
253256
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
254257

255258
return nil

cmd/utils/flags.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,10 +2055,16 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
20552055
if ctx.String(CryptoKZGFlag.Name) != "gokzg" && ctx.String(CryptoKZGFlag.Name) != "ckzg" {
20562056
Fatalf("--%s flag must be 'gokzg' or 'ckzg'", CryptoKZGFlag.Name)
20572057
}
2058-
log.Info("Initializing the KZG library", "backend", ctx.String(CryptoKZGFlag.Name))
2059-
if err := kzg4844.UseCKZG(ctx.String(CryptoKZGFlag.Name) == "ckzg"); err != nil {
2060-
Fatalf("Failed to set KZG library implementation to %s: %v", ctx.String(CryptoKZGFlag.Name), err)
2061-
}
2058+
// The initialization of the KZG library can take up to 2 seconds
2059+
// We start this here in parallel, so it should be available
2060+
// once we start executing blocks. It's threadsafe.
2061+
go func() {
2062+
log.Info("Initializing the KZG library", "backend", ctx.String(CryptoKZGFlag.Name))
2063+
if err := kzg4844.UseCKZG(ctx.String(CryptoKZGFlag.Name) == "ckzg"); err != nil {
2064+
Fatalf("Failed to set KZG library implementation to %s: %v", ctx.String(CryptoKZGFlag.Name), err)
2065+
}
2066+
}()
2067+
20622068
// VM tracing config.
20632069
if ctx.IsSet(VMTraceFlag.Name) {
20642070
if name := ctx.String(VMTraceFlag.Name); name != "" {

core/blockchain_reader.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
234234
return receipts
235235
}
236236

237+
func (bc *BlockChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts {
238+
number := rawdb.ReadHeaderNumber(bc.db, hash)
239+
if number == nil {
240+
return nil
241+
}
242+
return rawdb.ReadRawReceipts(bc.db, hash, *number)
243+
}
244+
237245
// GetUnclesInChain retrieves all the uncles from a given block backwards until
238246
// a specific distance is reached.
239247
func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.Header {
@@ -262,42 +270,20 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
262270
// GetTransactionLookup retrieves the lookup along with the transaction
263271
// itself associate with the given transaction hash.
264272
//
265-
// An error will be returned if the transaction is not found, and background
266-
// indexing for transactions is still in progress. The transaction might be
267-
// reachable shortly once it's indexed.
268-
//
269-
// A null will be returned in the transaction is not found and background
270-
// transaction indexing is already finished. The transaction is not existent
271-
// from the node's perspective.
272-
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
273+
// A null will be returned if the transaction is not found. This can be due to
274+
// the transaction indexer not being finished. The caller must explicitly check
275+
// the indexer progress.
276+
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction) {
273277
bc.txLookupLock.RLock()
274278
defer bc.txLookupLock.RUnlock()
275279

276280
// Short circuit if the txlookup already in the cache, retrieve otherwise
277281
if item, exist := bc.txLookupCache.Get(hash); exist {
278-
return item.lookup, item.transaction, nil
282+
return item.lookup, item.transaction
279283
}
280284
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
281285
if tx == nil {
282-
progress, err := bc.TxIndexProgress()
283-
if err != nil {
284-
// No error is returned if the transaction indexing progress is unreachable
285-
// due to unexpected internal errors. In such cases, it is impossible to
286-
// determine whether the transaction does not exist or has simply not been
287-
// indexed yet without a progress marker.
288-
//
289-
// In such scenarios, the transaction is treated as unreachable, though
290-
// this is clearly an unintended and unexpected situation.
291-
return nil, nil, nil
292-
}
293-
// The transaction indexing is not finished yet, returning an
294-
// error to explicitly indicate it.
295-
if !progress.Done() {
296-
return nil, nil, errors.New("transaction indexing still in progress")
297-
}
298-
// The transaction is already indexed, the transaction is either
299-
// not existent or not in the range of index, returning null.
300-
return nil, nil, nil
286+
return nil, nil
301287
}
302288
lookup := &rawdb.LegacyTxLookupEntry{
303289
BlockHash: blockHash,
@@ -308,7 +294,23 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
308294
lookup: lookup,
309295
transaction: tx,
310296
})
311-
return lookup, tx, nil
297+
return lookup, tx
298+
}
299+
300+
// TxIndexDone returns true if the transaction indexer has finished indexing.
301+
func (bc *BlockChain) TxIndexDone() bool {
302+
progress, err := bc.TxIndexProgress()
303+
if err != nil {
304+
// No error is returned if the transaction indexing progress is unreachable
305+
// due to unexpected internal errors. In such cases, it is impossible to
306+
// determine whether the transaction does not exist or has simply not been
307+
// indexed yet without a progress marker.
308+
//
309+
// In such scenarios, the transaction is treated as unreachable, though
310+
// this is clearly an unintended and unexpected situation.
311+
return true
312+
}
313+
return progress.Done()
312314
}
313315

314316
// HasState checks if state trie is fully present in the database or not.
@@ -414,7 +416,7 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
414416
if bc.txIndexer == nil {
415417
return TxIndexProgress{}, errors.New("tx indexer is not enabled")
416418
}
417-
return bc.txIndexer.txIndexProgress()
419+
return bc.txIndexer.txIndexProgress(), nil
418420
}
419421

420422
// HistoryPruningCutoff returns the configured history pruning point.

core/filtermaps/chain_view.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type blockchain interface {
2929
GetHeader(hash common.Hash, number uint64) *types.Header
3030
GetCanonicalHash(number uint64) common.Hash
3131
GetReceiptsByHash(hash common.Hash) types.Receipts
32+
GetRawReceiptsByHash(hash common.Hash) types.Receipts
3233
}
3334

3435
// ChainView represents an immutable view of a chain with a block id and a set
@@ -102,10 +103,23 @@ func (cv *ChainView) Receipts(number uint64) types.Receipts {
102103
blockHash := cv.BlockHash(number)
103104
if blockHash == (common.Hash{}) {
104105
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
106+
return nil
105107
}
106108
return cv.chain.GetReceiptsByHash(blockHash)
107109
}
108110

111+
// RawReceipts returns the set of receipts belonging to the block at the given
112+
// block number. Does not derive the fields of the receipts, should only be
113+
// used during creation of the filter maps, please use cv.Receipts during querying.
114+
func (cv *ChainView) RawReceipts(number uint64) types.Receipts {
115+
blockHash := cv.BlockHash(number)
116+
if blockHash == (common.Hash{}) {
117+
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
118+
return nil
119+
}
120+
return cv.chain.GetRawReceiptsByHash(blockHash)
121+
}
122+
109123
// SharedRange returns the block range shared by two chain views.
110124
func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
111125
cv.lock.Lock()
@@ -121,14 +135,6 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
121135
return common.NewRange(0, sharedLen)
122136
}
123137

124-
// limitedView returns a new chain view that is a truncated version of the parent view.
125-
func (cv *ChainView) limitedView(newHead uint64) *ChainView {
126-
if newHead >= cv.headNumber {
127-
return cv
128-
}
129-
return NewChainView(cv.chain, newHead, cv.BlockHash(newHead))
130-
}
131-
132138
// equalViews returns true if the two chain views are equivalent.
133139
func equalViews(cv1, cv2 *ChainView) bool {
134140
if cv1 == nil || cv2 == nil {

core/filtermaps/filtermaps.go

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var (
5050
)
5151

5252
const (
53-
databaseVersion = 1 // reindexed if database version does not match
53+
databaseVersion = 2 // reindexed if database version does not match
5454
cachedLastBlocks = 1000 // last block of map pointers
5555
cachedLvPointers = 1000 // first log value pointer of block pointers
5656
cachedBaseRows = 100 // groups of base layer filter row data
@@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
244244
disabledCh: make(chan struct{}),
245245
exportFileName: config.ExportFileName,
246246
Params: params,
247+
targetView: initView,
248+
indexedView: initView,
247249
indexedRange: filterMapsRange{
248250
initialized: initialized,
249251
headIndexed: rs.HeadIndexed,
@@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
265267
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
266268
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
267269
}
270+
f.checkRevertRange() // revert maps that are inconsistent with the current chain view
268271

269-
// Set initial indexer target.
270-
f.targetView = initView
271-
if f.indexedRange.initialized {
272-
f.indexedView = f.initChainView(f.targetView)
273-
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.HeadNumber()+1
274-
if !f.indexedRange.headIndexed {
275-
f.indexedRange.headDelimiter = 0
276-
}
277-
}
278272
if f.indexedRange.hasIndexedBlocks() {
279273
log.Info("Initialized log indexer",
280274
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
@@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
303297
f.closeWg.Wait()
304298
}
305299

306-
// initChainView returns a chain view consistent with both the current target
307-
// view and the current state of the log index as found in the database, based
308-
// on the last block of stored maps.
309-
// Note that the returned view might be shorter than the existing index if
310-
// the latest maps are not consistent with targetView.
311-
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
312-
mapIndex := f.indexedRange.maps.AfterLast()
313-
for {
314-
var ok bool
315-
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
316-
if !ok {
317-
break
300+
// checkRevertRange checks whether the existing index is consistent with the
301+
// current indexed view and reverts inconsistent maps if necessary.
302+
func (f *FilterMaps) checkRevertRange() {
303+
if f.indexedRange.maps.Count() == 0 {
304+
return
305+
}
306+
lastMap := f.indexedRange.maps.Last()
307+
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(lastMap)
308+
if err != nil {
309+
log.Error("Error initializing log index database; resetting log index", "error", err)
310+
f.reset()
311+
return
312+
}
313+
for lastBlockNumber > f.indexedView.HeadNumber() || f.indexedView.BlockId(lastBlockNumber) != lastBlockId {
314+
// revert last map
315+
if f.indexedRange.maps.Count() == 1 {
316+
f.reset() // reset database if no rendered maps remained
317+
return
318318
}
319-
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(mapIndex)
319+
lastMap--
320+
newRange := f.indexedRange
321+
newRange.maps.SetLast(lastMap)
322+
lastBlockNumber, lastBlockId, err = f.getLastBlockOfMap(lastMap)
320323
if err != nil {
321-
log.Error("Could not initialize indexed chain view", "error", err)
322-
break
323-
}
324-
if lastBlockNumber <= chainView.HeadNumber() && chainView.BlockId(lastBlockNumber) == lastBlockId {
325-
return chainView.limitedView(lastBlockNumber)
324+
log.Error("Error initializing log index database; resetting log index", "error", err)
325+
f.reset()
326+
return
326327
}
328+
newRange.blocks.SetAfterLast(lastBlockNumber) // lastBlockNumber is probably partially indexed
329+
newRange.headIndexed = false
330+
newRange.headDelimiter = 0
331+
// only shorten range and leave map data; next head render will overwrite it
332+
f.setRange(f.db, f.indexedView, newRange, false)
327333
}
328-
return chainView.limitedView(0)
329334
}
330335

331336
// reset un-initializes the FilterMaps structure and removes all related data from
@@ -662,15 +667,11 @@ func (f *FilterMaps) mapRowIndex(mapIndex, rowIndex uint32) uint64 {
662667
}
663668

664669
// getBlockLvPointer returns the starting log value index where the log values
665-
// generated by the given block are located. If blockNumber is beyond the current
666-
// head then the first unoccupied log value index is returned.
670+
// generated by the given block are located.
667671
//
668672
// Note that this function assumes that the indexer read lock is being held when
669673
// called from outside the indexerLoop goroutine.
670674
func (f *FilterMaps) getBlockLvPointer(blockNumber uint64) (uint64, error) {
671-
if blockNumber >= f.indexedRange.blocks.AfterLast() && f.indexedRange.headIndexed {
672-
return f.indexedRange.headDelimiter + 1, nil
673-
}
674675
if lvPointer, ok := f.lvPointerCache.Get(blockNumber); ok {
675676
return lvPointer, nil
676677
}

core/filtermaps/indexer.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ func (f *FilterMaps) tryIndexHead() error {
254254
((!f.loggedHeadIndex && time.Since(f.startedHeadIndexAt) > headLogDelay) ||
255255
time.Since(f.lastLogHeadIndex) > logFrequency) {
256256
log.Info("Log index head rendering in progress",
257-
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
257+
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
258258
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
259259
"remaining", f.indexedView.HeadNumber()-f.indexedRange.blocks.Last(),
260260
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
@@ -266,7 +266,7 @@ func (f *FilterMaps) tryIndexHead() error {
266266
}
267267
if f.loggedHeadIndex && f.indexedRange.hasIndexedBlocks() {
268268
log.Info("Log index head rendering finished",
269-
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
269+
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
270270
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
271271
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
272272
}
@@ -323,7 +323,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) {
323323
if f.indexedRange.hasIndexedBlocks() && f.ptrTailIndex >= f.indexedRange.blocks.First() &&
324324
(!f.loggedTailIndex || time.Since(f.lastLogTailIndex) > logFrequency) {
325325
log.Info("Log index tail rendering in progress",
326-
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
326+
"firstblock", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
327327
"processed", f.ptrTailIndex-f.indexedRange.blocks.First()+tpb,
328328
"remaining", remaining,
329329
"next tail epoch percentage", f.indexedRange.tailPartialEpoch*100/f.mapsPerEpoch,
@@ -346,7 +346,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) {
346346
}
347347
if f.loggedTailIndex && f.indexedRange.hasIndexedBlocks() {
348348
log.Info("Log index tail rendering finished",
349-
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
349+
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
350350
"processed", f.ptrTailIndex-f.indexedRange.blocks.First(),
351351
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
352352
f.loggedTailIndex = false

0 commit comments

Comments
 (0)