Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fe47c39
version: start v1.17.3 release cycle (#34619)
rjl493456442 Mar 30, 2026
965bd6b
eth: implement EIP-7975 (eth/70 - partial block receipt lists) (#33153)
healthykim Mar 30, 2026
dc3794e
core/rawdb: BAL storage layer (#34064)
jrhea Mar 31, 2026
3da517e
core/state: fix storage counters in binary trie IntermediateRoot (#34…
CPerezz Mar 31, 2026
92b4cb2
eth/tracers/logger: conform structLog tracing to spec (#34093)
MysticRyuujin Mar 31, 2026
fc43170
beacon/light: keep retrying checkpoint init if failed (#33966)
zsfelfoldi Apr 1, 2026
14a26d9
eth/gasestimator: fix block overrides in estimate gas (#34081)
gzliudan Apr 1, 2026
db6c7d0
triedb/pathdb: implement history index pruner (#33999)
rjl493456442 Apr 1, 2026
bcb0efd
core/types: copy block access list hash in CopyHeader (#34636)
cuiweixie Apr 2, 2026
0ba4314
core/state: introduce state iterator interface (#33102)
rjl493456442 Apr 3, 2026
00da4f5
core, eth/protocols/snap: Snap/2 Protocol + BAL Serving (#34083)
jrhea Apr 3, 2026
a608ac9
eth/protocols/snap: restore Bytes soft limit to GetAccessListsPacket …
jrhea Apr 4, 2026
d8cb8a9
core, eth, ethclient, triedb: report trienode index progress (#34633)
rjl493456442 Apr 4, 2026
4425795
tests: enable execution of amsterdam statetests (#34671)
holiman Apr 7, 2026
bd6530a
triedb, triedb/internal, triedb/pathdb: add GenerateTrie + extract sh…
jrhea Apr 7, 2026
b5d3220
eth/protocols/snap: fix block accessList encoding rule (#34644)
rjl493456442 Apr 7, 2026
52b8c09
triedb/pathdb: skip duplicate-root layer insertion (#34642)
diega Apr 7, 2026
0bafb29
core/types: add accessList to WithSeal and WithBody (#34651)
cuiweixie Apr 7, 2026
9878ef9
ethclient: omit empty address/topics fields in RPC filter requests (#…
locoholy Apr 7, 2026
04e4099
core: merge access events for all system calls (#34637)
DELENE-TCHIO-ROMUALD Apr 7, 2026
d9a3a0b
merge geth 04e40995d (v1.17.4 sync, batch 20/33 of v1.17.3)
pratikspatil024 Aug 3, 2026
d4d65aa
core/state: satisfy goimports on the Bor-only snapshot import
pratikspatil024 Aug 3, 2026
b85a293
Merge ppatil-corevm-catchup into ppatil-upstream-v1.17.3
pratikspatil024 Aug 5, 2026
d866cfd
Merge ppatil-corevm-catchup into ppatil-upstream-v1.17.3
pratikspatil024 Aug 5, 2026
7e3e238
Merge branch 'ppatil-corevm-catchup' into ppatil-upstream-v1.17.3 (de…
pratikspatil024 Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions beacon/light/request/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,11 @@ func (s *serverWithLimits) fail(desc string) {
// failLocked calculates the dynamic failure delay and applies it.
func (s *serverWithLimits) failLocked(desc string) {
log.Debug("Server error", "description", desc)
s.failureDelay *= 2
now := s.clock.Now()
if now > s.failureDelayEnd {
s.failureDelay *= math.Pow(2, -float64(now-s.failureDelayEnd)/float64(maxFailureDelay))
}
if s.failureDelay < float64(minFailureDelay) {
s.failureDelay = float64(minFailureDelay)
}
s.failureDelay = max(min(s.failureDelay*2, float64(maxFailureDelay)), float64(minFailureDelay))
s.failureDelayEnd = now + mclock.AbsTime(s.failureDelay)
s.delay(time.Duration(s.failureDelay))
}
4 changes: 2 additions & 2 deletions beacon/light/sync/update_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ const (
ssNeedParent // cp header slot %32 != 0, need parent to check epoch boundary
ssParentRequested // cp parent header requested
ssPrintStatus // has all necessary info, print log message if init still not successful
ssDone // log message printed, no more action required
)

type serverState struct {
Expand Down Expand Up @@ -180,7 +179,8 @@ func (s *CheckpointInit) Process(requester request.Requester, events []request.E
default:
log.Error("blsync: checkpoint not available, but reported as finalized; specified checkpoint hash might be too old", "server", server.Name())
}
s.serverState[server] = serverState{state: ssDone}
s.serverState[server] = serverState{state: ssDefault}
requester.Fail(server, "checkpoint init failed")
}
}

Expand Down
26 changes: 18 additions & 8 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,15 +292,25 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
}
}

// EIP-7843 SLOTNUM: post-Amsterdam headers must carry a slotNumber, pre-Amsterdam
// must not. Amsterdam is dormant on Bor (AmsterdamBlock nil), so IsAmsterdam is
// false and headers must not carry a slotNumber.
// Verify the existence / non-existence of Amsterdam-specific header fields.
// EIP-7843 SLOTNUM and the EIP-7928 block access list hash both key off
// Amsterdam, which is dormant on Bor (AmsterdamBlock nil), so IsAmsterdam is
// false and headers must carry neither field.
amsterdam := chain.Config().IsAmsterdam(header.Number)
if amsterdam && header.SlotNumber == nil {
return errors.New("header is missing slotNumber")
}
if !amsterdam && header.SlotNumber != nil {
return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber)
if amsterdam {
if header.BlockAccessListHash == nil {
return errors.New("header is missing block access list hash")
}
if header.SlotNumber == nil {
return errors.New("header is missing slotNumber")
}
} else {
if header.BlockAccessListHash != nil {
return fmt.Errorf("invalid block access list hash: have %x, expected nil", *header.BlockAccessListHash)
}
if header.SlotNumber != nil {
return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber)
}
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
}

// StateIndexProgress returns the historical state indexing progress.
func (bc *BlockChain) StateIndexProgress() (uint64, error) {
func (bc *BlockChain) StateIndexProgress() (uint64, uint64, error) {
return bc.triedb.IndexProgress()
}

Expand Down
66 changes: 64 additions & 2 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -828,6 +829,55 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
}
}

// HasAccessList verifies the existence of a block access list for a block.
func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool {
has, _ := db.Has(accessListKey(number, hash))
return has
}

// ReadAccessListRLP retrieves the RLP-encoded block access list for a block from KV.
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(accessListKey(number, hash))
return data
}

// ReadAccessList retrieves and decodes the block access list for a block.
func ReadAccessList(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList {
data := ReadAccessListRLP(db, hash, number)
if len(data) == 0 {
return nil
}
b := new(bal.BlockAccessList)
if err := rlp.DecodeBytes(data, b); err != nil {
log.Error("Invalid BAL RLP", "hash", hash, "err", err)
return nil
}
return b
}

// WriteAccessList RLP-encodes and stores a block access list in the active KV store.
func WriteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b *bal.BlockAccessList) {
bytes, err := rlp.EncodeToBytes(b)
if err != nil {
log.Crit("Failed to encode BAL", "err", err)
}
WriteAccessListRLP(db, hash, number, bytes)
}

// WriteAccessListRLP stores a pre-encoded block access list in the active KV store.
func WriteAccessListRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, encoded rlp.RawValue) {
if err := db.Put(accessListKey(number, hash), encoded); err != nil {
log.Crit("Failed to store BAL", "err", err)
}
}

// DeleteAccessList removes a block access list from the active KV store.
func DeleteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(accessListKey(number, hash)); err != nil {
log.Crit("Failed to delete BAL", "err", err)
}
}

// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps
// the list of logs. When decoding a stored receipt into this object we
// avoid creating the bloom filter.
Expand Down Expand Up @@ -883,13 +933,25 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
if body == nil {
return nil
}
return types.NewBlockWithHeader(header).WithBody(*body)
block := types.NewBlockWithHeader(header).WithBody(*body)

// Best-effort assembly of the block access list from the database.
if header.BlockAccessListHash != nil {
al := ReadAccessList(db, hash, number)
block = block.WithAccessListUnsafe(al)
}
return block
}

// WriteBlock serializes a block into the database, header and body separately.
func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
hash, number := block.Hash(), block.NumberU64()
WriteBody(db, hash, number, block.Body())
WriteHeader(db, block.Header())

if accessList := block.AccessList(); accessList != nil {
WriteAccessList(db, hash, number, accessList)
}
}

// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
Expand Down
77 changes: 77 additions & 0 deletions core/rawdb/accessors_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/keccak"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/uint256"
)

// Tests block header storage and retrieval operations.
Expand Down Expand Up @@ -1224,3 +1226,78 @@ func TestWriteBlockPruneHead(t *testing.T) {
}
}
}

func makeTestBAL(t *testing.T) (rlp.RawValue, *bal.BlockAccessList) {
t.Helper()

cb := bal.NewConstructionBlockAccessList()
addr := common.HexToAddress("0x1111111111111111111111111111111111111111")
cb.AccountRead(addr)
cb.StorageRead(addr, common.BytesToHash([]byte{0x01}))
cb.StorageWrite(0, addr, common.BytesToHash([]byte{0x02}), common.BytesToHash([]byte{0xaa}))
cb.BalanceChange(0, addr, uint256.NewInt(100))
cb.NonceChange(addr, 0, 1)

var buf bytes.Buffer
if err := cb.EncodeRLP(&buf); err != nil {
t.Fatalf("failed to encode BAL: %v", err)
}
encoded := buf.Bytes()

var decoded bal.BlockAccessList
if err := rlp.DecodeBytes(encoded, &decoded); err != nil {
t.Fatalf("failed to decode BAL: %v", err)
}
return encoded, &decoded
}

// TestBALStorage tests write/read/delete of BALs in the KV store.
func TestBALStorage(t *testing.T) {
db := NewMemoryDatabase()

hash := common.BytesToHash([]byte{0x03, 0x14})
number := uint64(42)

// Check that no BAL exists in a new database.
if HasAccessList(db, hash, number) {
t.Fatal("BAL found in new database")
}
if b := ReadAccessList(db, hash, number); b != nil {
t.Fatalf("non existent BAL returned: %v", b)
}

// Write a BAL and verify it can be read back.
encoded, testBAL := makeTestBAL(t)
WriteAccessList(db, hash, number, testBAL)

if !HasAccessList(db, hash, number) {
t.Fatal("HasAccessList returned false after write")
}
if blob := ReadAccessListRLP(db, hash, number); len(blob) == 0 {
t.Fatal("ReadAccessListRLP returned empty after write")
}
if b := ReadAccessList(db, hash, number); b == nil {
t.Fatal("ReadAccessList returned nil after write")
} else if b.Hash() != testBAL.Hash() {
t.Fatalf("BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
}

// Also test WriteAccessListRLP with pre-encoded data.
hash2 := common.BytesToHash([]byte{0x03, 0x15})
WriteAccessListRLP(db, hash2, number, encoded)
if b := ReadAccessList(db, hash2, number); b == nil {
t.Fatal("ReadAccessList returned nil after WriteAccessListRLP")
} else if b.Hash() != testBAL.Hash() {
t.Fatalf("BAL hash mismatch after WriteAccessListRLP: got %x, want %x", b.Hash(), testBAL.Hash())
}

// Delete the BAL and verify it's gone.
DeleteAccessList(db, hash, number)

if HasAccessList(db, hash, number) {
t.Fatal("HasAccessList returned true after delete")
}
if b := ReadAccessList(db, hash, number); b != nil {
t.Fatalf("deleted BAL returned: %v", b)
}
}
5 changes: 5 additions & 0 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
tds stat
numHashPairings stat
hashNumPairings stat
blockAccessList stat
legacyTries stat
stateLookups stat
accountTries stat
Expand Down Expand Up @@ -721,6 +722,9 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
numHashPairings.add(size)
case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength):
hashNumPairings.add(size)
case bytes.HasPrefix(key, accessListPrefix) && len(key) == len(accessListPrefix)+8+common.HashLength:
blockAccessList.add(size)

case IsLegacyTrieNode(key, it.Value()):
legacyTries.add(size)
case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength:
Expand Down Expand Up @@ -862,6 +866,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
{"Key-Value store", "Difficulties", tds.sizeString(), tds.countString()},
{"Key-Value store", "Block number->hash", numHashPairings.sizeString(), numHashPairings.countString()},
{"Key-Value store", "Block hash->number", hashNumPairings.sizeString(), hashNumPairings.countString()},
{"Key-Value store", "Block accessList", blockAccessList.sizeString(), blockAccessList.countString()},
{"Key-Value store", "Transaction index", txLookups.sizeString(), txLookups.countString()},
{"Key-Value store", "Log index filter-map rows", filterMapRows.sizeString(), filterMapRows.countString()},
{"Key-Value store", "Log index last-block-of-map", filterMapLastBlock.sizeString(), filterMapLastBlock.countString()},
Expand Down
7 changes: 7 additions & 0 deletions core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ var (
BlockPruneCursorKey = []byte("blockPruneCursorKey")
BlockPruneHeadKey = []byte("blockPruneHeadKey")

accessListPrefix = []byte("j") // accessListPrefix + num (uint64 big endian) + hash -> block access list

txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata
bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value
Expand Down Expand Up @@ -251,6 +253,11 @@ func blockReceiptsKey(number uint64, hash common.Hash) []byte {
return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}

// accessListKey = accessListPrefix + num (uint64 big endian) + hash
func accessListKey(number uint64, hash common.Hash) []byte {
return append(append(accessListPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}

// txLookupKey = txLookupPrefix + hash
func txLookupKey(hash common.Hash) []byte {
return append(txLookupPrefix, hash.Bytes()...)
Expand Down
9 changes: 9 additions & 0 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ type Database interface {
// Reader returns a state reader associated with the specified state root.
Reader(root common.Hash) (Reader, error)

// Iteratee returns a state iteratee associated with the specified state root,
// through which the account iterator and storage iterator can be created.
Iteratee(root common.Hash) (Iteratee, error)

// OpenTrie opens the main account trie.
OpenTrie(root common.Hash) (Trie, error)

Expand Down Expand Up @@ -337,6 +341,11 @@ func (db *CachingDB) Snapshot() *snapshot.Tree {
return db.snap
}

// Iteratee returns a state iteratee associated with the specified state root.
func (db *CachingDB) Iteratee(root common.Hash) (Iteratee, error) {
return newStateIteratee(!db.triedb.IsVerkle(), root, db.triedb, db.snap)
}

// mustCopyTrie returns a deep-copied trie.
func mustCopyTrie(t Trie) Trie {
switch t := t.(type) {
Expand Down
6 changes: 6 additions & 0 deletions core/state/database_history.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package state

import (
"errors"
"fmt"
"sync"

Expand Down Expand Up @@ -298,3 +299,8 @@ func (db *HistoricDB) TrieDB() *triedb.Database {
func (db *HistoricDB) Snapshot() *snapshot.Tree {
return nil
}

// Iteratee returns a state iteratee associated with the specified state root.
func (db *HistoricDB) Iteratee(root common.Hash) (Iteratee, error) {
return nil, errors.New("not implemented")
}
Loading
Loading