From d74c47f8dbaf5af43c1a58e932a6849089d3fdf3 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 6 Feb 2025 15:06:46 +0100 Subject: [PATCH 01/47] version: begin v1.15.1 release cycle --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index b6dfc70b12..f700f9e973 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 0 // Patch version component of the current release - Meta = "stable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 1 // Patch version component of the current release + Meta = "unstable" // Version metadata to append to the version string ) From d11e9c0b517364ae3a372af48f0b34f754e1dbc0 Mon Sep 17 00:00:00 2001 From: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Fri, 7 Feb 2025 02:59:12 +0100 Subject: [PATCH 02/47] cmd/devp2p/internal/ethtest: remove TD from status validation (#31137) After recent changes in Geth (removing TD): https://github.com/ethereum/go-ethereum/commit/39638c81c56db2b2dfe6f51999ffd3029ee212cb#diff-d70a44d4b7a0e84fe9dcca25d368f626ae6c9bc0b8fe9690074ba92d298bcc0d Non-Geth clients are failing many devp2p tests with an error: `peering failed: status exchange failed: wrong TD in status: have 1 want 0` Right now only Geth is passing it - all other clients are affected by this change. I think there should be no validation of TD when checking `Status` message in hive tests. Now Geth has 0 (and hive tests requires 0) and all other clients have actual TD. And on real networks there is no validation of TD when peering --- cmd/devp2p/internal/ethtest/conn.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go index 757b137aa1..b555b14784 100644 --- a/cmd/devp2p/internal/ethtest/conn.go +++ b/cmd/devp2p/internal/ethtest/conn.go @@ -316,9 +316,6 @@ loop: return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x", want, chain.blocks[chain.Len()-1].NumberU64(), have) } - if have, want := msg.TD.Cmp(chain.TD()), 0; have != want { - return fmt.Errorf("wrong TD in status: have %v want %v", have, want) - } if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) { return fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want) } From 4cda8f06ea688cc3e523ee1e35425393ecad807c Mon Sep 17 00:00:00 2001 From: lightclient <14004106+lightclient@users.noreply.github.com> Date: Sat, 8 Feb 2025 05:26:15 -0700 Subject: [PATCH 03/47] params,core/forkid: enable prague on holesky and sepolia (#31139) Agreed to the following fork dates for Holesky and Sepolia on ACDC 150 Holesky slot: 3710976 (Mon, Feb 24 at 21:55:12 UTC) Sepolia slot: 7118848 (Wed, Mar 5 at 07:29:36 UTC) --- core/forkid/forkid_test.go | 12 ++++++++---- params/config.go | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index de589c0d44..bebc20ad9d 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -91,8 +91,10 @@ func TestCreation(t *testing.T) { {1735372, 1677557087, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last MergeNetsplit block {1735372, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // First Shanghai block {1735372, 1706655071, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // Last Shanghai block - {1735372, 1706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // First Cancun block - {1735372, 2706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // Future Cancun block + {1735372, 1706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 1741159776}}, // First Cancun block + {1735372, 1741159775, ID{Hash: checksumToBytes(0x88cf81d9), Next: 1741159776}}, // Last Cancun block + {1735372, 1741159776, ID{Hash: checksumToBytes(0xed88b5fd), Next: 0}}, // First Prague block + {1735372, 2741159776, ID{Hash: checksumToBytes(0xed88b5fd), Next: 0}}, // Future Prague block }, }, // Holesky test cases @@ -104,8 +106,10 @@ func TestCreation(t *testing.T) { {123, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // First MergeNetsplit block {123, 1696000704, ID{Hash: checksumToBytes(0xfd4f016b), Next: 1707305664}}, // First Shanghai block {123, 1707305663, ID{Hash: checksumToBytes(0xfd4f016b), Next: 1707305664}}, // Last Shanghai block - {123, 1707305664, ID{Hash: checksumToBytes(0x9b192ad0), Next: 0}}, // First Cancun block - {123, 2707305664, ID{Hash: checksumToBytes(0x9b192ad0), Next: 0}}, // Future Cancun block + {123, 1707305664, ID{Hash: checksumToBytes(0x9b192ad0), Next: 1740434112}}, // First Cancun block + {123, 1740434111, ID{Hash: checksumToBytes(0x9b192ad0), Next: 1740434112}}, // Last Cancun block + {123, 1740434112, ID{Hash: checksumToBytes(0xdfbd9bed), Next: 0}}, // First Prague block + {123, 2740434112, ID{Hash: checksumToBytes(0xdfbd9bed), Next: 0}}, // Future Prague block }, }, } diff --git a/params/config.go b/params/config.go index 0dbe4c509a..cb12098bc9 100644 --- a/params/config.go +++ b/params/config.go @@ -87,9 +87,11 @@ var ( MergeNetsplitBlock: nil, ShanghaiTime: newUint64(1696000704), CancunTime: newUint64(1707305664), + PragueTime: newUint64(1740434112), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, + Prague: DefaultPragueBlobConfig, }, } // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. @@ -114,9 +116,11 @@ var ( MergeNetsplitBlock: big.NewInt(1735371), ShanghaiTime: newUint64(1677557088), CancunTime: newUint64(1706655072), + PragueTime: newUint64(1741159776), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, + Prague: DefaultPragueBlobConfig, }, } // AllEthashProtocolChanges contains every protocol change (EIPs) introduced From 9064038a86eead5f181d065a8ceb9ca2dc09fdbc Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 11 Feb 2025 13:44:25 +0100 Subject: [PATCH 04/47] consensus/beacon: remove TestingTTDBlock (#31153) This removes the method `TestingTTDBlock` introduced by #30744. It was added to make the beacon consensus engine aware of the merge block in tests without relying on the total difficulty. However, tracking the merge block this way is very annoying. We usually configure forks in the `ChainConfig`, but the method is on the consensus engine, which isn't always created in the same place. By sidestepping the `ChainConfig` we don't get the usual fork-order checking, so it's possible to enable the merge before the London fork, for example. This in turn can lead to very hard-to-debug outputs and validation errors. So here I'm changing the consensus engine to check the `MergeNetsplitBlock` instead. Alternatively, we assume a network is merged if it has a `TerminalTotalDifficulty` of zero, which is a very common configuration in tests. --- consensus/beacon/consensus.go | 39 +++++-------------- eth/catalyst/api_test.go | 5 ++- eth/gasprice/gasprice_test.go | 11 +++--- eth/protocols/eth/handler_test.go | 4 +- eth/tracers/internal/tracetest/supply_test.go | 3 -- graphql/graphql_test.go | 7 +--- 6 files changed, 21 insertions(+), 48 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index bdfddfff06..d80d24e272 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -61,8 +61,7 @@ var ( // is only used for necessary consensus checks. The legacy consensus engine can be any // engine implements the consensus interface (except the beacon itself). type Beacon struct { - ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique - ttdblock *uint64 // Merge block-number for testchain generation without TTDs + ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique } // New creates a consensus engine with the given embedded eth1 engine. @@ -73,16 +72,12 @@ func New(ethone consensus.Engine) *Beacon { return &Beacon{ethone: ethone} } -// TestingTTDBlock is a replacement mechanism for TTD-based pre-/post-merge -// splitting. With chain history deletion, TD calculations become impossible. -// This is fine for progressing the live chain, but to be able to generate test -// chains, we do need a split point. This method supports setting an explicit -// block number to use as the splitter *for testing*, instead of having to keep -// the notion of TDs in the client just for testing. -// -// The block with supplied number is regarded as the last pre-merge block. -func (beacon *Beacon) TestingTTDBlock(number uint64) { - beacon.ttdblock = &number +// isPostMerge reports whether the given block number is assumed to be post-merge. +// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or +// PoA chain for unit testing purposes. +func isPostMerge(config *params.ChainConfig, block uint64) bool { + mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0 + return mergedAtGenesis || config.MergeNetsplitBlock != nil && block >= config.MergeNetsplitBlock.Uint64() } // Author implements consensus.Engine, returning the verified author of the block. @@ -332,15 +327,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [ // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the beacon protocol. The changes are done inline. func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - // The beacon engine requires access to total difficulties to be able to - // seal pre-merge and post-merge blocks. With the transition to removing - // old blocks, TDs become unaccessible, thus making TTD based pre-/post- - // merge decisions impossible. - // - // We do not need to seal non-merge blocks anymore live, but we do need - // to be able to generate test chains, thus we're reverting to a testing- - // settable field to direct that. - if beacon.ttdblock != nil && *beacon.ttdblock >= header.Number.Uint64() { + if !isPostMerge(chain.Config(), header.Number.Uint64()) { return beacon.ethone.Prepare(chain, header) } header.Difficulty = beaconDifficulty @@ -450,15 +437,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash { // the difficulty that a new block should have when created at time // given the parent block's time and difficulty. func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - // The beacon engine requires access to total difficulties to be able to - // seal pre-merge and post-merge blocks. With the transition to removing - // old blocks, TDs become unaccessible, thus making TTD based pre-/post- - // merge decisions impossible. - // - // We do not need to seal non-merge blocks anymore live, but we do need - // to be able to generate test chains, thus we're reverting to a testing- - // settable field to direct that. - if beacon.ttdblock != nil && *beacon.ttdblock > parent.Number.Uint64() { + if !isPostMerge(chain.Config(), parent.Number.Uint64()+1) { return beacon.ethone.CalcDifficulty(chain, time, parent) } return beaconDifficulty diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 8fc3361192..e91e07d05d 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -64,9 +64,12 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { engine := beacon.New(ethash.NewFaker()) if merged { config.TerminalTotalDifficulty = common.Big0 + config.MergeNetsplitBlock = common.Big0 } else { - engine.TestingTTDBlock(uint64(n)) + // When !merged, the tests expect the next block after the generated chain to be in PoS. + config.MergeNetsplitBlock = big.NewInt(int64(n + 1)) } + genesis := &core.Genesis{ Config: &config, Alloc: types.GenesisAlloc{ diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 0a32c278cb..8e6524446f 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -147,11 +147,11 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe config.LondonBlock = londonBlock config.ArrowGlacierBlock = londonBlock config.GrayGlacierBlock = londonBlock - + if cancunBlock != nil { + // Enable the merge with cancun fork. + config.MergeNetsplitBlock = cancunBlock + } engine := beacon.New(ethash.NewFaker()) - engine.TestingTTDBlock(testHead + 1) - - td := params.GenesisDifficulty.Uint64() if cancunBlock != nil { ts := gspec.Timestamp + cancunBlock.Uint64()*10 // fixed 10 sec block time in blockgen @@ -209,10 +209,9 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe b.AddTx(types.MustSignNewTx(key, signer, blobTx)) } } - td += b.Difficulty().Uint64() }) + // Construct testing chain - gspec.Config.TerminalTotalDifficulty = new(big.Int).SetUint64(td) chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil) if err != nil { t.Fatalf("Failed to create local chain, %v", err) diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index 5b35a2f935..f92599dba7 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -74,9 +74,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int, config = params.TestChainConfig engine = beacon.New(ethash.NewFaker()) ) - if !shanghai { - engine.TestingTTDBlock(math.MaxUint64) - } else { + if shanghai { config = ¶ms.ChainConfig{ ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), diff --git a/eth/tracers/internal/tracetest/supply_test.go b/eth/tracers/internal/tracetest/supply_test.go index 3d54ab1868..57ba628b78 100644 --- a/eth/tracers/internal/tracetest/supply_test.go +++ b/eth/tracers/internal/tracetest/supply_test.go @@ -75,8 +75,6 @@ func TestSupplyOmittedFields(t *testing.T) { } ) - gspec.Config.TerminalTotalDifficulty = big.NewInt(0) - out, _, err := testSupplyTracer(t, gspec, func(b *core.BlockGen) { b.SetPoS() }) @@ -546,7 +544,6 @@ func TestSupplySelfdestructItselfAndRevert(t *testing.T) { func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockGen)) ([]supplyInfo, *core.BlockChain, error) { engine := beacon.New(ethash.NewFaker()) - engine.TestingTTDBlock(1) traceOutputPath := filepath.ToSlash(t.TempDir()) traceOutputFilename := path.Join(traceOutputPath, "supply.jsonl") diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go index 3e6a042dbb..0f6ba10b90 100644 --- a/graphql/graphql_test.go +++ b/graphql/graphql_test.go @@ -21,7 +21,6 @@ import ( "encoding/json" "fmt" "io" - "math" "math/big" "net/http" "strings" @@ -459,15 +458,13 @@ func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Ge var engine = beacon.New(ethash.NewFaker()) if shanghai { gspec.Config.TerminalTotalDifficulty = common.Big0 + gspec.Config.MergeNetsplitBlock = common.Big0 // GenerateChain will increment timestamps by 10. // Shanghai upgrade at block 1. shanghaiTime := uint64(5) gspec.Config.ShanghaiTime = &shanghaiTime - } else { - // set an arbitrary large ttd as chains are required to be known to be merged - gspec.Config.TerminalTotalDifficulty = big.NewInt(math.MaxInt64) - engine.TestingTTDBlock(math.MaxUint64) } + ethBackend, err := eth.New(stack, ethConf) if err != nil { t.Fatalf("could not create eth backend: %v", err) From d2ca7cf9f190d190495cd9f12b3b1f79f8513b8c Mon Sep 17 00:00:00 2001 From: Harry Ngo <17699212+huyngopt1994@users.noreply.github.com> Date: Tue, 11 Feb 2025 19:45:44 +0700 Subject: [PATCH 05/47] p2p/discover: remove unused parameter in revalidationList.get (#31155) --- p2p/discover/table_reval.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/p2p/discover/table_reval.go b/p2p/discover/table_reval.go index 2465fee906..1519313d19 100644 --- a/p2p/discover/table_reval.go +++ b/p2p/discover/table_reval.go @@ -79,7 +79,7 @@ func (tr *tableRevalidation) nodeEndpointChanged(tab *Table, n *tableNode) { func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) (nextTime mclock.AbsTime) { reval := func(list *revalidationList) { if list.nextTime <= now { - if n := list.get(now, &tab.rand, tr.activeReq); n != nil { + if n := list.get(&tab.rand, tr.activeReq); n != nil { tr.startRequest(tab, n) } // Update nextTime regardless if any requests were started because @@ -203,7 +203,7 @@ type revalidationList struct { } // get returns a random node from the queue. Nodes in the 'exclude' map are not returned. -func (list *revalidationList) get(now mclock.AbsTime, rand randomSource, exclude map[enode.ID]struct{}) *tableNode { +func (list *revalidationList) get(rand randomSource, exclude map[enode.ID]struct{}) *tableNode { if len(list.nodes) == 0 { return nil } From 22b935449499e37526b63bc56583a757fc6bf1b5 Mon Sep 17 00:00:00 2001 From: Chen Kai <281165273grape@gmail.com> Date: Tue, 11 Feb 2025 20:52:43 +0800 Subject: [PATCH 06/47] p2p/discover: make discv5 response timeout configurable (#31119) --- p2p/discover/common.go | 8 ++++++-- p2p/discover/v5_udp.go | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/p2p/discover/common.go b/p2p/discover/common.go index cabc5c7962..767cc23b92 100644 --- a/p2p/discover/common.go +++ b/p2p/discover/common.go @@ -49,8 +49,9 @@ type Config struct { // All remaining settings are optional. // Packet handling configuration: - NetRestrict *netutil.Netlist // list of allowed IP networks - Unhandled chan<- ReadPacket // unhandled packets are sent on this channel + NetRestrict *netutil.Netlist // list of allowed IP networks + Unhandled chan<- ReadPacket // unhandled packets are sent on this channel + V5RespTimeout time.Duration // timeout for v5 queries // Node table configuration: Bootnodes []*enode.Node // list of bootstrap nodes @@ -73,6 +74,9 @@ func (cfg Config) withDefaults() Config { if cfg.RefreshInterval == 0 { cfg.RefreshInterval = 30 * time.Minute } + if cfg.V5RespTimeout == 0 { + cfg.V5RespTimeout = 700 * time.Millisecond + } // Debug/test settings: if cfg.Log == nil { diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index 4453d10695..48256ea4de 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -42,8 +42,6 @@ const ( lookupRequestLimit = 3 // max requests against a single node during lookup findnodeResultLimit = 16 // applies in FINDNODE handler totalNodesResponseLimit = 5 // applies in waitForNodes - - respTimeoutV5 = 700 * time.Millisecond ) // codecV5 is implemented by v5wire.Codec (and testCodec). @@ -71,6 +69,7 @@ type UDPv5 struct { log log.Logger clock mclock.Clock validSchemes enr.IdentityScheme + respTimeout time.Duration // misc buffers used during message handling logcontext []interface{} @@ -158,6 +157,7 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) { log: cfg.Log, validSchemes: cfg.ValidSchemes, clock: cfg.Clock, + respTimeout: cfg.V5RespTimeout, // channels into dispatch packetInCh: make(chan ReadPacket, 1), readNextCh: make(chan struct{}, 1), @@ -576,7 +576,7 @@ func (t *UDPv5) startResponseTimeout(c *callV5) { timer mclock.Timer done = make(chan struct{}) ) - timer = t.clock.AfterFunc(respTimeoutV5, func() { + timer = t.clock.AfterFunc(t.respTimeout, func() { <-done select { case t.respTimeoutCh <- &callTimeout{c, timer}: From cdb66c89d6f8de3afd5e8d72bb5a0e3f46c27362 Mon Sep 17 00:00:00 2001 From: lightclient <14004106+lightclient@users.noreply.github.com> Date: Tue, 11 Feb 2025 06:15:04 -0700 Subject: [PATCH 07/47] core/txpool/legacypool: add support for SetCode transactions (#31073) The new SetCode transaction type introduces some additional complexity when handling the transaction pool. This complexity stems from two new account behaviors: 1. The balance and nonce of an account can change during regular transaction execution *when they have a deployed delegation*. 2. The nonce and code of an account can change without any EVM execution at all. This is the "set code" mechanism introduced by EIP-7702. The first issue has already been considered extensively during the design of ERC-4337, and we're relatively confident in the solution of simply limiting the number of in-flight pending transactions an account can have to one. This puts a reasonable bound on transaction cancellation. Normally to cancel, you would need to spend 21,000 gas. Now it's possible to cancel for around the cost of warming the account and sending value (`2,600+9,000=11,600`). So 50% cheaper. The second issue is more novel and needs further consideration. Since authorizations are not bound to a specific transaction, we cannot drop transactions with conflicting authorizations. Otherwise, it might be possible to cherry-pick authorizations from txs and front run them with different txs at much lower fee amounts, effectively DoSing the authority. Fortunately, conflicting authorizations do not affect the underlying validity of the transaction so we can just accept both. --------- Co-authored-by: Marius van der Wijden Co-authored-by: Felix Lange --- core/txpool/blobpool/blobpool_test.go | 6 +- core/txpool/errors.go | 9 + core/txpool/legacypool/legacypool.go | 89 +++++++- core/txpool/legacypool/legacypool_test.go | 234 +++++++++++++++++++++- core/txpool/validation.go | 32 ++- core/types/transaction.go | 15 ++ 6 files changed, 368 insertions(+), 17 deletions(-) diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index f7c9e4844b..8589e5c01d 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -142,6 +142,7 @@ func (bc *testBlockChain) CurrentBlock() *types.Header { GasLimit: gasLimit, BaseFee: baseFee, ExcessBlobGas: &excessBlobGas, + Difficulty: common.Big0, } } @@ -1565,8 +1566,9 @@ func TestAdd(t *testing.T) { if tt.block != nil { // Fake a header for the new set of transactions header := &types.Header{ - Number: big.NewInt(int64(chain.CurrentBlock().Number.Uint64() + 1)), - BaseFee: chain.CurrentBlock().BaseFee, // invalid, but nothing checks it, yolo + Number: big.NewInt(int64(chain.CurrentBlock().Number.Uint64() + 1)), + Difficulty: common.Big0, + BaseFee: chain.CurrentBlock().BaseFee, // invalid, but nothing checks it, yolo } // Inject the fake block into the chain txs := make([]*types.Transaction, len(tt.block)) diff --git a/core/txpool/errors.go b/core/txpool/errors.go index 3a6a913976..32e49db87c 100644 --- a/core/txpool/errors.go +++ b/core/txpool/errors.go @@ -60,4 +60,13 @@ var ( // input transaction of non-blob type when a blob transaction from this sender // remains pending (and vice-versa). ErrAlreadyReserved = errors.New("address already reserved") + + // ErrAuthorityReserved is returned if a transaction has an authorization + // signed by an address which already has in-flight transactions known to the + // pool. + ErrAuthorityReserved = errors.New("authority already reserved") + + // ErrAuthorityNonce is returned if a transaction has an authorization with + // a nonce that is not currently valid for the authority. + ErrAuthorityNonceTooLow = errors.New("authority nonce too low") ) diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 1440af5440..c7ff954a49 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -21,6 +21,7 @@ import ( "errors" "math" "math/big" + "slices" "sort" "sync" "sync/atomic" @@ -196,6 +197,20 @@ func (config *Config) sanitize() Config { // The pool separates processable transactions (which can be applied to the // current state) and future transactions. Transactions move between those // two states over time as they are received and processed. +// +// In addition to tracking transactions, the pool also tracks a set of pending SetCode +// authorizations (EIP7702). This helps minimize number of transactions that can be +// trivially churned in the pool. As a standard rule, any account with a deployed +// delegation or an in-flight authorization to deploy a delegation will only be allowed a +// single transaction slot instead of the standard number. This is due to the possibility +// of the account being sweeped by an unrelated account. +// +// Because SetCode transactions can have many authorizations included, we avoid explicitly +// checking their validity to save the state lookup. So long as the encompassing +// transaction is valid, the authorization will be accepted and tracked by the pool. In +// case the pool is tracking a pending / queued transaction from a specific account, it +// will reject new transactions with delegations from that account with standard in-flight +// transactions. type LegacyPool struct { config Config chainconfig *params.ChainConfig @@ -263,7 +278,7 @@ func New(config Config, chain BlockChain) *LegacyPool { // pool, specifically, whether it is a Legacy, AccessList or Dynamic transaction. func (pool *LegacyPool) Filter(tx *types.Transaction) bool { switch tx.Type() { - case types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType: + case types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType, types.SetCodeTxType: return true default: return false @@ -540,7 +555,8 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction) error { Accept: 0 | 1<= 0 { + list = append(list[:i], list[i+1:]...) + } else { + log.Error("Authority with untracked tx", "addr", addr, "hash", hash) + } + if len(list) == 0 { + // If list is newly empty, delete it entirely. + delete(t.auths, addr) + continue + } + t.auths[addr] = list + } +} + // numSlots calculates the number of slots needed for a single transaction. func numSlots(tx *types.Transaction) int { return int((tx.Size() + txSlotSize - 1) / txSlotSize) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index fdbcad3d4f..da28e8a75b 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" @@ -79,8 +80,9 @@ func (bc *testBlockChain) Config() *params.ChainConfig { func (bc *testBlockChain) CurrentBlock() *types.Header { return &types.Header{ - Number: new(big.Int), - GasLimit: bc.gasLimit.Load(), + Number: new(big.Int), + Difficulty: common.Big0, + GasLimit: bc.gasLimit.Load(), } } @@ -128,6 +130,39 @@ func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int, return tx } +type unsignedAuth struct { + nonce uint64 + key *ecdsa.PrivateKey +} + +func setCodeTx(nonce uint64, key *ecdsa.PrivateKey, unsigned []unsignedAuth) *types.Transaction { + return pricedSetCodeTx(nonce, 250000, uint256.NewInt(1000), uint256.NewInt(1), key, unsigned) +} + +func pricedSetCodeTx(nonce uint64, gaslimit uint64, gasFee, tip *uint256.Int, key *ecdsa.PrivateKey, unsigned []unsignedAuth) *types.Transaction { + var authList []types.SetCodeAuthorization + for _, u := range unsigned { + auth, _ := types.SignSetCode(u.key, types.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(params.TestChainConfig.ChainID), + Address: common.Address{0x42}, + Nonce: u.nonce, + }) + authList = append(authList, auth) + } + return types.MustSignNewTx(key, types.LatestSignerForChainID(params.TestChainConfig.ChainID), &types.SetCodeTx{ + ChainID: uint256.MustFromBig(params.TestChainConfig.ChainID), + Nonce: nonce, + GasTipCap: tip, + GasFeeCap: gasFee, + Gas: gaslimit, + To: common.Address{}, + Value: uint256.NewInt(100), + Data: nil, + AccessList: nil, + AuthList: authList, + }) +} + func makeAddressReserver() txpool.AddressReserver { var ( reserved = make(map[common.Address]struct{}) @@ -2163,6 +2198,201 @@ func TestSlotCount(t *testing.T) { } } +// TestSetCodeTransactions tests a few scenarios regarding the EIP-7702 +// SetCodeTx. +func TestSetCodeTransactions(t *testing.T) { + t.Parallel() + + // Create the pool to test the status retrievals with + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + blockchain := newTestBlockChain(params.MergedTestChainConfig, 1000000, statedb, new(event.Feed)) + + pool := New(testTxPoolConfig, blockchain) + pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) + defer pool.Close() + + // Create the test accounts + var ( + keyA, _ = crypto.GenerateKey() + keyB, _ = crypto.GenerateKey() + keyC, _ = crypto.GenerateKey() + addrA = crypto.PubkeyToAddress(keyA.PublicKey) + addrB = crypto.PubkeyToAddress(keyB.PublicKey) + addrC = crypto.PubkeyToAddress(keyC.PublicKey) + ) + testAddBalance(pool, addrA, big.NewInt(params.Ether)) + testAddBalance(pool, addrB, big.NewInt(params.Ether)) + testAddBalance(pool, addrC, big.NewInt(params.Ether)) + + for _, tt := range []struct { + name string + pending int + queued int + run func(string) + }{ + { + // Check that only one in-flight transaction is allowed for accounts + // with delegation set. Also verify the accepted transaction can be + // replaced by fee. + name: "only-one-in-flight", + pending: 1, + run: func(name string) { + aa := common.Address{0xaa, 0xaa} + statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...)) + statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}) + // Send transactions. First is accepted, second is rejected. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyA)); err != nil { + t.Fatalf("%s: failed to add remote transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + } + // Also check gapped transaction. + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + } + // Replace by fee. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keyA)); err != nil { + t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) + } + }, + }, + { + name: "allow-setcode-tx-with-pending-authority-tx", + pending: 2, + run: func(name string) { + // Send two transactions where the first has no conflicting delegations and + // the second should be allowed despite conflicting with the authorities in 1). + if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(setCodeTx(0, keyB, []unsignedAuth{{1, keyC}})); err != nil { + t.Fatalf("%s: failed to add conflicting delegation: %v", name, err) + } + }, + }, + { + name: "allow-one-tx-from-pooled-delegation", + pending: 2, + run: func(name string) { + // Verify C cannot originate another transaction when it has a pooled delegation. + if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{0, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyC)); err != nil { + t.Fatalf("%s: failed to add with pending delegatio: %v", name, err) + } + // Also check gapped transaction is rejected. + if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + } + }, + }, + { + name: "replace-by-fee-setcode-tx", + pending: 1, + run: func(name string) { + // 4. Fee bump the setcode tx send. + if err := pool.addRemoteSync(setCodeTx(0, keyB, []unsignedAuth{{1, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(2000), uint256.NewInt(2), keyB, []unsignedAuth{{0, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + }, + }, + { + name: "allow-tx-from-replaced-authority", + pending: 2, + run: func(name string) { + // Fee bump with a different auth list. Make sure that unlocks the authorities. + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyB}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(3000), uint256.NewInt(300), keyA, []unsignedAuth{{0, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + // Now send a regular tx from B. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keyB)); err != nil { + t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) + } + }, + }, + { + name: "allow-tx-from-replaced-self-sponsor-authority", + pending: 2, + run: func(name string) { + // + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyA}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(30), uint256.NewInt(30), keyA, []unsignedAuth{{0, keyB}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + // Now send a regular tx from keyA. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyA)); err != nil { + t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) + } + // Make sure we can still send from keyB. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyB)); err != nil { + t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) + } + }, + }, + { + name: "track-multiple-conflicting-delegations", + pending: 3, + run: func(name string) { + // Send two setcode txs both with C as an authority. + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(30), uint256.NewInt(30), keyB, []unsignedAuth{{0, keyC}})); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + // Replace the tx from A with a non-setcode tx. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyA)); err != nil { + t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) + } + // Make sure we can only pool one tx from keyC since it is still a + // pending authority. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { + t.Fatalf("%s: failed to added single pooled for account with pending delegation: %v", name, err) + } + if err, want := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1000), keyC)), txpool.ErrAccountLimitExceeded; !errors.Is(err, want) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) + } + }, + }, + { + name: "reject-delegation-from-pending-account", + pending: 1, + run: func(name string) { + // Attempt to submit a delegation from an account with a pending tx. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err, want := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})), txpool.ErrAuthorityReserved; !errors.Is(err, want) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) + } + }, + }, + } { + tt.run(tt.name) + pending, queued := pool.Stats() + if pending != tt.pending { + t.Fatalf("%s: pending transactions mismatched: have %d, want %d", tt.name, pending, tt.pending) + } + if queued != tt.queued { + t.Fatalf("%s: queued transactions mismatched: have %d, want %d", tt.name, queued, tt.queued) + } + if err := validatePoolInternals(pool); err != nil { + t.Fatalf("%s: pool internal state corrupted: %v", tt.name, err) + } + pool.Clear() + } +} + // Benchmarks the speed of validating the contents of the pending queue of the // transaction pool. func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 8cd13776a6..4d53c386b6 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -70,17 +70,21 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return fmt.Errorf("%w: transaction size %v, limit %v", ErrOversizedData, tx.Size(), opts.MaxSize) } // Ensure only transactions that have been enabled are accepted - if !opts.Config.IsBerlin(head.Number) && tx.Type() != types.LegacyTxType { + rules := opts.Config.Rules(head.Number, head.Difficulty.Sign() == 0, head.Time) + if !rules.IsBerlin && tx.Type() != types.LegacyTxType { return fmt.Errorf("%w: type %d rejected, pool not yet in Berlin", core.ErrTxTypeNotSupported, tx.Type()) } - if !opts.Config.IsLondon(head.Number) && tx.Type() == types.DynamicFeeTxType { + if !rules.IsLondon && tx.Type() == types.DynamicFeeTxType { return fmt.Errorf("%w: type %d rejected, pool not yet in London", core.ErrTxTypeNotSupported, tx.Type()) } - if !opts.Config.IsCancun(head.Number, head.Time) && tx.Type() == types.BlobTxType { + if !rules.IsCancun && tx.Type() == types.BlobTxType { return fmt.Errorf("%w: type %d rejected, pool not yet in Cancun", core.ErrTxTypeNotSupported, tx.Type()) } + if !rules.IsPrague && tx.Type() == types.SetCodeTxType { + return fmt.Errorf("%w: type %d rejected, pool not yet in Prague", core.ErrTxTypeNotSupported, tx.Type()) + } // Check whether the init code size has been exceeded - if opts.Config.IsShanghai(head.Number, head.Time) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { + if rules.IsShanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) } // Transactions can't be negative. This may never happen using RLP decoded @@ -109,7 +113,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Ensure the transaction has more gas than the bare minimum needed to cover // the transaction metadata - intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time)) + intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, rules.IsIstanbul, rules.IsShanghai) if err != nil { return err } @@ -154,6 +158,11 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return err } } + if tx.Type() == types.SetCodeTxType { + if len(tx.SetCodeAuthorizations()) == 0 { + return fmt.Errorf("set code tx must have at least one authorization tuple") + } + } return nil } @@ -209,6 +218,11 @@ type ValidationOptionsWithState struct { // ExistingCost is a mandatory callback to retrieve an already pooled // transaction's cost with the given nonce to check for overdrafts. ExistingCost func(addr common.Address, nonce uint64) *big.Int + + // KnownConflicts is an optional callback which iterates over the list of + // addresses and returns all addresses known to the pool with in-flight + // transactions. + KnownConflicts func(sender common.Address, authorizers []common.Address) []common.Address } // ValidateTransactionWithState is a helper method to check whether a transaction @@ -262,6 +276,14 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op if used, left := opts.UsedAndLeftSlots(from); left <= 0 { return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used) } + + // Verify no authorizations will invalidate existing transactions known to + // the pool. + if opts.KnownConflicts != nil { + if conflicts := opts.KnownConflicts(from, tx.SetCodeAuthorities()); len(conflicts) > 0 { + return fmt.Errorf("%w: authorization conflicts with other known tx", ErrAuthorityReserved) + } + } } return nil } diff --git a/core/types/transaction.go b/core/types/transaction.go index 35dc1ea3f9..7df13e04bb 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -483,6 +483,21 @@ func (tx *Transaction) SetCodeAuthorizations() []SetCodeAuthorization { return setcodetx.AuthList } +// SetCodeAuthorities returns a list of each authorization's corresponding authority. +func (tx *Transaction) SetCodeAuthorities() []common.Address { + setcodetx, ok := tx.inner.(*SetCodeTx) + if !ok { + return nil + } + auths := make([]common.Address, 0, len(setcodetx.AuthList)) + for _, auth := range setcodetx.AuthList { + if addr, err := auth.Authority(); err == nil { + auths = append(auths, addr) + } + } + return auths +} + // SetTime sets the decoding time of a transaction. This is used by tests to set // arbitrary times and by persistent transaction pools when loading old txs from // disk. From da71839a270a353bac92e3108e4b74fb0eefec29 Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:02:30 +0100 Subject: [PATCH 08/47] internal/ethapi: fix panic in debug methods (#31157) Fixes an error when the block is not found in debug methods. --- internal/ethapi/api.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index c0b37c516b..92249f7829 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1675,7 +1675,7 @@ func (api *DebugAPI) GetRawHeader(ctx context.Context, blockNrOrHash rpc.BlockNu hash = h } else { block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash) - if err != nil { + if block == nil || err != nil { return nil, err } hash = block.Hash() @@ -1694,7 +1694,7 @@ func (api *DebugAPI) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNum hash = h } else { block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash) - if err != nil { + if block == nil || err != nil { return nil, err } hash = block.Hash() @@ -1713,7 +1713,7 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block hash = h } else { block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash) - if err != nil { + if block == nil || err != nil { return nil, err } hash = block.Hash() From 58f65c60c29873f480f5a6f2718b1fe68a8da9bd Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 11 Feb 2025 17:55:00 -0800 Subject: [PATCH 09/47] trie: copy preimage store pointer in StateTrie.Copy (#31158) This fixes an error where executing `evm run --dump ...` omits preimages from the dump (because the statedb used for execution is a copy of another instance). --- cmd/evm/testdata/evmrun/3.out.1.txt | 3 ++- cmd/evm/testdata/evmrun/4.out.1.txt | 3 ++- trie/secure_trie.go | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/evm/testdata/evmrun/3.out.1.txt b/cmd/evm/testdata/evmrun/3.out.1.txt index 44956f54f6..25dd8da5a1 100644 --- a/cmd/evm/testdata/evmrun/3.out.1.txt +++ b/cmd/evm/testdata/evmrun/3.out.1.txt @@ -1,12 +1,13 @@ { "root": "b444481d1367188172f8c6091e948aaa68bae763fd26d6b9e994306a66bf69f9", "accounts": { - "pre(0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142)": { + "0x0000000000000000000000007265636569766572": { "balance": "0", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0x3e48ef54b89079a075f3b8fc253c657a86b110a7aed3568c1517b10edf2c3eb6", "code": "0x6040", + "address": "0x0000000000000000000000007265636569766572", "key": "0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142" } } diff --git a/cmd/evm/testdata/evmrun/4.out.1.txt b/cmd/evm/testdata/evmrun/4.out.1.txt index 44956f54f6..25dd8da5a1 100644 --- a/cmd/evm/testdata/evmrun/4.out.1.txt +++ b/cmd/evm/testdata/evmrun/4.out.1.txt @@ -1,12 +1,13 @@ { "root": "b444481d1367188172f8c6091e948aaa68bae763fd26d6b9e994306a66bf69f9", "accounts": { - "pre(0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142)": { + "0x0000000000000000000000007265636569766572": { "balance": "0", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0x3e48ef54b89079a075f3b8fc253c657a86b110a7aed3568c1517b10edf2c3eb6", "code": "0x6040", + "address": "0x0000000000000000000000007265636569766572", "key": "0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142" } } diff --git a/trie/secure_trie.go b/trie/secure_trie.go index f53b10758f..45d5fd63e7 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -275,6 +275,7 @@ func (t *StateTrie) Copy() *StateTrie { trie: *t.trie.Copy(), db: t.db, secKeyCache: t.secKeyCache, + preimages: t.preimages, } } From 24ed0b506602cf18e92c2ec5b75173a68178748b Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 13 Feb 2025 09:45:27 +0100 Subject: [PATCH 10/47] go.mod: update blst to v0.3.14 (#31165) closes https://github.com/ethereum/go-ethereum/issues/31072 BLST released their newest version which includes a fix for go v.1.24: https://github.com/supranational/blst/releases/tag/v0.3.14 I went through all commits between 0.3.14 and 0.3.13 for a sanity check --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fc768460c7..cf9fda50c8 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.2.0 github.com/stretchr/testify v1.9.0 - github.com/supranational/blst v0.3.13 + github.com/supranational/blst v0.3.14 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 diff --git a/go.sum b/go.sum index 82836a5d8c..9812cbbab5 100644 --- a/go.sum +++ b/go.sum @@ -508,8 +508,8 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= -github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= From 8ec4a06b3f0686a3c181c5f88c899390ee80fb60 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 13 Feb 2025 13:05:05 +0100 Subject: [PATCH 11/47] core: sanity-check fork configuration in genesis (#31171) This is to prevent a crash on startup with a custom genesis configuration. With this change in place, upgrading a chain created by geth v1.14.x and below will now print an error instead of crashing: Fatal: Failed to register the Ethereum service: invalid chain configuration: missing entry for fork "cancun" in blobSchedule Arguably this is not great, and it should just auto-upgrade the config. We'll address this in a follow-up PR for geth v1.15.2 --- core/genesis.go | 5 +++++ params/config.go | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index 8546f4e37e..4dd6c9ed24 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -364,6 +364,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g } newCfg := genesis.chainConfigOrDefault(ghash, storedCfg) + // Sanity-check the new configuration. + if err := newCfg.CheckConfigForkOrder(); err != nil { + return nil, common.Hash{}, nil, err + } + // TODO(rjl493456442) better to define the comparator of chain config // and short circuit if the chain config is not changed. compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time) diff --git a/params/config.go b/params/config.go index cb12098bc9..5a2e10a943 100644 --- a/params/config.go +++ b/params/config.go @@ -735,13 +735,13 @@ func (c *ChainConfig) CheckConfigForkOrder() error { } { if cur.config != nil { if err := cur.config.validate(); err != nil { - return fmt.Errorf("invalid blob configuration for fork %s: %v", cur.name, err) + return fmt.Errorf("invalid chain configuration in blobSchedule for fork %q: %v", cur.name, err) } } if cur.timestamp != nil { // If the fork is configured, a blob schedule must be defined for it. if cur.config == nil { - return fmt.Errorf("unsupported fork configuration: missing blob configuration entry for %v in schedule", cur.name) + return fmt.Errorf("invalid chain configuration: missing entry for fork %q in blobSchedule", cur.name) } } } From 913fee4be9e7b825bf6c6ff87918dde93a1be7ac Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 13 Feb 2025 21:48:03 +0800 Subject: [PATCH 12/47] core/rawdb: skip setting flushOffset in read-only mode (#31173) This PR addresses a flaw in the freezer table upgrade path. In v1.15.0, freezer table v2 was introduced, including an additional field (`flushOffset`) maintained in the metadata file. To ensure backward compatibility, an upgrade path was implemented for legacy freezer tables by setting `flushOffset` to the size of the index file. However, if the freezer table is opened in read-only mode, this file write operation is rejected, causing Geth to shut down entirely. Given that invalid items in the freezer index file can be detected and truncated, all items in freezer v0 index files are guaranteed to be complete. Therefore, when operating in read-only mode, it is safe to use the freezer data without performing an upgrade. --- core/rawdb/freezer_table.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go index 1ba8cf639f..e553df7029 100644 --- a/core/rawdb/freezer_table.go +++ b/core/rawdb/freezer_table.go @@ -405,6 +405,13 @@ func (t *freezerTable) repairIndex() error { // If legacy metadata is detected, attempt to recover the offset from the // index file to avoid clearing the entire table. if t.metadata.version == freezerTableV1 { + // Skip truncation if the legacy metadata is opened in read-only mode. + // Since all items in the legacy index file were forcibly synchronized, + // data integrity is guaranteed. Therefore, it's safe to leave any extra + // items untruncated in this special scenario. + if t.readonly { + return nil + } t.logger.Info("Recovering freezer flushOffset for legacy table", "offset", size) return t.metadata.setFlushOffset(size, true) } From b027a90ac06d6483a9ac8b5e961b3d6a92d59273 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 13 Feb 2025 16:21:36 +0100 Subject: [PATCH 13/47] version: release go-ethereum v1.15.1 stable --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index f700f9e973..c97634d7a9 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 1 // Patch version component of the current release - Meta = "unstable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 1 // Patch version component of the current release + Meta = "stable" // Version metadata to append to the version string ) From 77762820c9d1ec6cc33ab97ede61861772011756 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 13 Feb 2025 16:26:36 +0100 Subject: [PATCH 14/47] version: begin v1.15.2 release cycle --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index c97634d7a9..374522e438 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 1 // Patch version component of the current release - Meta = "stable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 2 // Patch version component of the current release + Meta = "unstable" // Version metadata to append to the version string ) From 68de26e34649e50c1f8f8a858a686c38274848b6 Mon Sep 17 00:00:00 2001 From: minh-bq Date: Fri, 14 Feb 2025 00:05:58 +0700 Subject: [PATCH 15/47] core/types: create block's bloom by merging receipts' bloom (#31129) Currently, when calculating block's bloom, we loop through all the receipt logs to calculate the hash value. However, normally, after going through applyTransaction, the receipt's bloom is already calculated based on the receipt log, so the block's bloom can be calculated by just ORing these receipt's blooms. ``` goos: darwin goarch: arm64 pkg: github.com/ethereum/go-ethereum/core/types cpu: Apple M1 Pro BenchmarkCreateBloom BenchmarkCreateBloom/small BenchmarkCreateBloom/small-10 810922 1481 ns/op 104 B/op 5 allocs/op BenchmarkCreateBloom/large BenchmarkCreateBloom/large-10 8173 143764 ns/op 9614 B/op 401 allocs/op BenchmarkCreateBloom/small-mergebloom BenchmarkCreateBloom/small-mergebloom-10 5178918 232.0 ns/op 0 B/op 0 allocs/op BenchmarkCreateBloom/large-mergebloom BenchmarkCreateBloom/large-mergebloom-10 54110 22207 ns/op 0 B/op 0 allocs/op ``` --------- Co-authored-by: Gary Rong Co-authored-by: Zsolt Felfoldi --- cmd/evm/internal/t8ntool/execution.go | 5 +-- core/block_validator.go | 6 +++- core/rawdb/accessors_chain_test.go | 8 ++--- core/state_processor.go | 2 +- core/types/block.go | 8 ++++- core/types/bloom9.go | 39 ++++++++++---------- core/types/bloom9_test.go | 52 ++++++++++++++++++++++++--- core/types/receipt.go | 2 +- core/types/receipt_test.go | 12 +++---- eth/filters/filter_test.go | 2 +- 10 files changed, 97 insertions(+), 39 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 16c8808360..7de1eb6949 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -304,7 +304,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, // Set the receipt logs and create the bloom filter. receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) + // These three are non-consensus fields: //receipt.BlockHash //receipt.BlockNumber @@ -376,7 +377,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, StateRoot: root, TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)), ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)), - Bloom: types.CreateBloom(receipts), + Bloom: types.MergeBloom(receipts), LogsHash: rlpHash(statedb.Logs()), Receipts: receipts, Rejected: rejectedTxs, diff --git a/core/block_validator.go b/core/block_validator.go index 5885df9ee2..591e472bc1 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -129,7 +129,11 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD } // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. - rbloom := types.CreateBloom(res.Receipts) + // + // Receipts must go through MakeReceipt to calculate the receipt's bloom + // already. Merge the receipt's bloom together instead of recalculating + // everything. + rbloom := types.MergeBloom(res.Receipts) if rbloom != header.Bloom { return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) } diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index b9684f8e17..efd16d5fa7 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -338,7 +338,7 @@ func TestBlockReceiptStorage(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: 111111, } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) + receipt1.Bloom = types.CreateBloom(receipt1) receipt2 := &types.Receipt{ PostState: common.Hash{2}.Bytes(), @@ -351,7 +351,7 @@ func TestBlockReceiptStorage(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: 222222, } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) + receipt2.Bloom = types.CreateBloom(receipt2) receipts := []*types.Receipt{receipt1, receipt2} // Check that no receipt entries are in a pristine database @@ -679,7 +679,7 @@ func TestReadLogs(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: 111111, } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) + receipt1.Bloom = types.CreateBloom(receipt1) receipt2 := &types.Receipt{ PostState: common.Hash{2}.Bytes(), @@ -692,7 +692,7 @@ func TestReadLogs(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: 222222, } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) + receipt2.Bloom = types.CreateBloom(receipt2) receipts := []*types.Receipt{receipt1, receipt2} hash := common.BytesToHash([]byte{0x03, 0x14}) diff --git a/core/state_processor.go b/core/state_processor.go index 902ff582e8..2c74f6f407 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -189,7 +189,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b // Set the receipt logs and create the bloom filter. receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) receipt.BlockHash = blockHash receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) diff --git a/core/types/block.go b/core/types/block.go index c3db4d89e8..b284fb3b16 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -237,6 +237,9 @@ type extblock struct { // // The body elements and the receipts are used to recompute and overwrite the // relevant portions of the header. +// +// The receipt's bloom must already calculated for the block's bloom to be +// correctly calculated. func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block { if body == nil { body = &Body{} @@ -260,7 +263,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher b.header.ReceiptHash = EmptyReceiptsHash } else { b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) - b.header.Bloom = CreateBloom(receipts) + // Receipts must go through MakeReceipt to calculate the receipt's bloom + // already. Merge the receipt's bloom together instead of recalculating + // everything. + b.header.Bloom = MergeBloom(receipts) } if len(uncles) == 0 { diff --git a/core/types/bloom9.go b/core/types/bloom9.go index a560a20724..962ba46d47 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -100,32 +100,35 @@ func (b *Bloom) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedText("Bloom", input, b[:]) } -// CreateBloom creates a bloom filter out of the give Receipts (+Logs) -func CreateBloom(receipts Receipts) Bloom { - buf := make([]byte, 6) - var bin Bloom - for _, receipt := range receipts { - for _, log := range receipt.Logs { - bin.add(log.Address.Bytes(), buf) - for _, b := range log.Topics { - bin.add(b[:], buf) - } +// CreateBloom creates a bloom filter out of the give Receipt (+Logs) +func CreateBloom(receipt *Receipt) Bloom { + var ( + bin Bloom + buf = make([]byte, 6) + ) + for _, log := range receipt.Logs { + bin.add(log.Address.Bytes(), buf) + for _, b := range log.Topics { + bin.add(b[:], buf) } } return bin } -// LogsBloom returns the bloom bytes for the given logs -func LogsBloom(logs []*Log) []byte { - buf := make([]byte, 6) +// MergeBloom merges the precomputed bloom filters in the Receipts without +// recalculating them. It assumes that each receipt’s Bloom field is already +// correctly populated. +func MergeBloom(receipts Receipts) Bloom { var bin Bloom - for _, log := range logs { - bin.add(log.Address.Bytes(), buf) - for _, b := range log.Topics { - bin.add(b[:], buf) + for _, receipt := range receipts { + if len(receipt.Logs) != 0 { + bl := receipt.Bloom.Bytes() + for i := range bin { + bin[i] |= bl[i] + } } } - return bin[:] + return bin } // Bloom9 returns the bloom filter for the given data diff --git a/core/types/bloom9_test.go b/core/types/bloom9_test.go index d3178d112e..07f6446a97 100644 --- a/core/types/bloom9_test.go +++ b/core/types/bloom9_test.go @@ -126,26 +126,70 @@ func BenchmarkCreateBloom(b *testing.B) { for i := 0; i < 200; i += 2 { copy(rLarge[i:], rSmall) } - b.Run("small", func(b *testing.B) { + b.Run("small-createbloom", func(b *testing.B) { b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, receipt := range rSmall { + receipt.Bloom = CreateBloom(receipt) + } + } + b.StopTimer() + + bl := MergeBloom(rSmall) + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") + got := crypto.Keccak256Hash(bl.Bytes()) + if got != exp { + b.Errorf("Got %x, exp %x", got, exp) + } + }) + b.Run("large-createbloom", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, receipt := range rLarge { + receipt.Bloom = CreateBloom(receipt) + } + } + b.StopTimer() + + bl := MergeBloom(rLarge) + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") + got := crypto.Keccak256Hash(bl.Bytes()) + if got != exp { + b.Errorf("Got %x, exp %x", got, exp) + } + }) + b.Run("small-mergebloom", func(b *testing.B) { + for _, receipt := range rSmall { + receipt.Bloom = CreateBloom(receipt) + } + b.ReportAllocs() + b.ResetTimer() + var bl Bloom for i := 0; i < b.N; i++ { - bl = CreateBloom(rSmall) + bl = MergeBloom(rSmall) } b.StopTimer() + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") got := crypto.Keccak256Hash(bl.Bytes()) if got != exp { b.Errorf("Got %x, exp %x", got, exp) } }) - b.Run("large", func(b *testing.B) { + b.Run("large-mergebloom", func(b *testing.B) { + for _, receipt := range rLarge { + receipt.Bloom = CreateBloom(receipt) + } b.ReportAllocs() + b.ResetTimer() + var bl Bloom for i := 0; i < b.N; i++ { - bl = CreateBloom(rLarge) + bl = MergeBloom(rLarge) } b.StopTimer() + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") got := crypto.Keccak256Hash(bl.Bytes()) if got != exp { diff --git a/core/types/receipt.go b/core/types/receipt.go index 47f16d950a..e52a0c6477 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -291,7 +291,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { } r.CumulativeGasUsed = stored.CumulativeGasUsed r.Logs = stored.Logs - r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) + r.Bloom = CreateBloom((*Receipt)(r)) return nil } diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index fc51eb11a5..78b43c7e49 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -394,7 +394,7 @@ func TestTypedReceiptEncodingDecoding(t *testing.T) { func TestReceiptMarshalBinary(t *testing.T) { // Legacy Receipt - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) + legacyReceipt.Bloom = CreateBloom(legacyReceipt) have, err := legacyReceipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -421,7 +421,7 @@ func TestReceiptMarshalBinary(t *testing.T) { // 2930 Receipt buf.Reset() - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) + accessListReceipt.Bloom = CreateBloom(accessListReceipt) have, err = accessListReceipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -439,7 +439,7 @@ func TestReceiptMarshalBinary(t *testing.T) { // 1559 Receipt buf.Reset() - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) + eip1559Receipt.Bloom = CreateBloom(eip1559Receipt) have, err = eip1559Receipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -463,7 +463,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) + legacyReceipt.Bloom = CreateBloom(legacyReceipt) if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt) } @@ -474,7 +474,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) + accessListReceipt.Bloom = CreateBloom(accessListReceipt) if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt) } @@ -485,7 +485,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) + eip1559Receipt.Bloom = CreateBloom(eip1559Receipt) if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt) } diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 6a3057326d..e2790d91eb 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -42,7 +42,7 @@ func makeReceipt(addr common.Address) *types.Receipt { receipt.Logs = []*types.Log{ {Address: addr}, } - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) return receipt } From e5bc789185e74a776d122b95e490639068a6a612 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 17 Feb 2025 07:30:06 +0100 Subject: [PATCH 16/47] consensus/beacon: fix isPostMerge for mainnet (#31191) This fixes a regression introduced in #31153 where we didn't consider mainnet to be in PoS, causing #31190. The problem is, `params.MainnetChainConfig` does not have a defined `MergeNetsplitBlock`, so it isn't considered to be in PoS in `CalcDifficulty`. --- consensus/beacon/consensus.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index d80d24e272..cc9f44e460 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -75,9 +75,11 @@ func New(ethone consensus.Engine) *Beacon { // isPostMerge reports whether the given block number is assumed to be post-merge. // Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or // PoA chain for unit testing purposes. -func isPostMerge(config *params.ChainConfig, block uint64) bool { +func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool { mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0 - return mergedAtGenesis || config.MergeNetsplitBlock != nil && block >= config.MergeNetsplitBlock.Uint64() + return mergedAtGenesis || + config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() || + config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime } // Author implements consensus.Engine, returning the verified author of the block. @@ -327,7 +329,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [ // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the beacon protocol. The changes are done inline. func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - if !isPostMerge(chain.Config(), header.Number.Uint64()) { + if !isPostMerge(chain.Config(), header.Number.Uint64(), header.Time) { return beacon.ethone.Prepare(chain, header) } header.Difficulty = beaconDifficulty @@ -437,7 +439,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash { // the difficulty that a new block should have when created at time // given the parent block's time and difficulty. func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - if !isPostMerge(chain.Config(), parent.Number.Uint64()+1) { + if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) { return beacon.ethone.CalcDifficulty(chain, time, parent) } return beaconDifficulty From c113e3b5b12619c80b962a3b6e895a14a13eaa75 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 17 Feb 2025 09:47:12 +0100 Subject: [PATCH 17/47] p2p: fix marshaling of NAT in TOML (#31192) This fixes an issue where a nat.Interface unmarshaled from the TOML config file could not be re-marshaled to TOML correctly. Fixes #31183 --- p2p/config.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/p2p/config.go b/p2p/config.go index 5ea62e12f5..68a9c0bb5f 100644 --- a/p2p/config.go +++ b/p2p/config.go @@ -18,6 +18,7 @@ package p2p import ( "crypto/ecdsa" + "encoding" "fmt" "github.com/ethereum/go-ethereum/common/mclock" @@ -135,6 +136,13 @@ type configNAT struct { nat.Interface } +func (w *configNAT) MarshalText() ([]byte, error) { + if tm, ok := w.Interface.(encoding.TextMarshaler); ok { + return tm.MarshalText() + } + return nil, fmt.Errorf("NAT specification %#v cannot be marshaled", w.Interface) +} + func (w *configNAT) UnmarshalText(input []byte) error { n, err := nat.Parse(string(input)) if err != nil { From d37a0b8cd0ad799dd696c25249987d89394a1409 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 17 Feb 2025 10:12:03 +0100 Subject: [PATCH 18/47] eth/protocols/eth: add discovery iterator to protocol (#31185) We somehow forgot to add this in #30302, so discv5 and DNS have actually been disabled since then. Fixes #31168 --- eth/protocols/eth/handler.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index d6cd83373b..a0848137fa 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -89,7 +89,7 @@ type TxPool interface { } // MakeProtocols constructs the P2P protocol definitions for `eth`. -func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol { +func MakeProtocols(backend Backend, network uint64, disc enode.Iterator) []p2p.Protocol { protocols := make([]p2p.Protocol, 0, len(ProtocolVersions)) for _, version := range ProtocolVersions { protocols = append(protocols, p2p.Protocol{ @@ -110,7 +110,8 @@ func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2 PeerInfo: func(id enode.ID) interface{} { return backend.PeerInfo(id) }, - Attributes: []enr.Entry{currentENREntry(backend.Chain())}, + DialCandidates: disc, + Attributes: []enr.Entry{currentENREntry(backend.Chain())}, }) } return protocols From c8c62dafc78b0edadfa9406503cef2d957299f8b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 17 Feb 2025 11:59:48 +0100 Subject: [PATCH 19/47] version: release go-ethereum v1.15.2 stable --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index 374522e438..9854aa1119 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 2 // Patch version component of the current release - Meta = "unstable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 2 // Patch version component of the current release + Meta = "stable" // Version metadata to append to the version string ) From aec1964410648e1eda9e70685f27e846f2328c0f Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 17 Feb 2025 12:01:20 +0100 Subject: [PATCH 20/47] version: begin v1.15.3 release cycle --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index 9854aa1119..f0fb3195b3 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 2 // Patch version component of the current release - Meta = "stable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 3 // Patch version component of the current release + Meta = "unstable" // Version metadata to append to the version string ) From 3adfa1fbeb8b8711ca67221fff63d4d670fdf95b Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 18 Feb 2025 03:48:42 +0100 Subject: [PATCH 21/47] trie: do not expect ordering in stacktrie during fuzzing (#31170) This PR removes the assumption of the stacktrie and trie to have the same ordering. This was hit by the fuzzers on oss-fuzz --------- Co-authored-by: Gary Rong --- trie/stacktrie_fuzzer_test.go | 25 ++++++++++------------ trie/trie_test.go | 39 ++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/trie/stacktrie_fuzzer_test.go b/trie/stacktrie_fuzzer_test.go index df487d16bf..7ff6ef0235 100644 --- a/trie/stacktrie_fuzzer_test.go +++ b/trie/stacktrie_fuzzer_test.go @@ -37,16 +37,13 @@ func FuzzStackTrie(f *testing.F) { } func fuzz(data []byte, debugging bool) { - // This spongeDb is used to check the sequence of disk-db-writes var ( - input = bytes.NewReader(data) - spongeA = &spongeDb{sponge: crypto.NewKeccakState()} - dbA = newTestDatabase(rawdb.NewDatabase(spongeA), rawdb.HashScheme) - trieA = NewEmpty(dbA) - spongeB = &spongeDb{sponge: crypto.NewKeccakState()} - dbB = newTestDatabase(rawdb.NewDatabase(spongeB), rawdb.HashScheme) - trieB = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme()) + input = bytes.NewReader(data) + dbA = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) + trieA = NewEmpty(dbA) + memDB = rawdb.NewMemoryDatabase() + trieB = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { + rawdb.WriteTrieNode(memDB, common.Hash{}, path, hash, blob, rawdb.HashScheme) }) vals []*kv maxElements = 10000 @@ -55,13 +52,17 @@ func fuzz(data []byte, debugging bool) { ) // Fill the trie with elements for i := 0; input.Len() > 0 && i < maxElements; i++ { + // Build the key k := make([]byte, 32) input.Read(k) + + // Build the val var a uint16 binary.Read(input, binary.LittleEndian, &a) a = 1 + a%100 v := make([]byte, a) input.Read(v) + if input.Len() == 0 { // If it was exhausted while reading, the value may be all zeroes, // thus 'deletion' which is not supported on stacktrie @@ -73,6 +74,7 @@ func fuzz(data []byte, debugging bool) { } keys[string(k)] = struct{}{} vals = append(vals, &kv{k: k, v: v}) + trieA.MustUpdate(k, v) } if len(vals) == 0 { @@ -99,11 +101,6 @@ func fuzz(data []byte, debugging bool) { if rootA != rootB { panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB)) } - sumA := spongeA.sponge.Sum(nil) - sumB := spongeB.sponge.Sum(nil) - if !bytes.Equal(sumA, sumB) { - panic(fmt.Sprintf("sequence differ: (trie) %x != %x (stacktrie)", sumA, sumB)) - } // Ensure all the nodes are persisted correctly var ( diff --git a/trie/trie_test.go b/trie/trie_test.go index 423ed30fe8..77234d9d9b 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -779,6 +779,7 @@ func TestCommitAfterHash(t *testing.T) { func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { // Make the random benchmark deterministic random := rand.New(rand.NewSource(0)) + // Create a realistic account trie to hash addresses = make([][20]byte, size) for i := 0; i < len(addresses); i++ { @@ -795,13 +796,18 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { ) // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, // and will consume different amount of data from the rand source. - //balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) + // balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) // Therefore, we instead just read via byte buffer numBytes := random.Uint32() % 33 // [0, 32] bytes balanceBytes := make([]byte, numBytes) random.Read(balanceBytes) balance := new(uint256.Int).SetBytes(balanceBytes) - data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code}) + data, _ := rlp.EncodeToBytes(&types.StateAccount{ + Nonce: nonce, + Balance: balance, + Root: root, + CodeHash: code, + }) accounts[i] = data } return addresses, accounts @@ -856,6 +862,7 @@ func (s *spongeDb) Flush() { s.sponge.Write([]byte(key)) s.sponge.Write([]byte(s.values[key])) } + fmt.Println(len(s.keys)) } // spongeBatch is a dummy batch which immediately writes to the underlying spongedb @@ -873,10 +880,12 @@ func (b *spongeBatch) Write() error { return nil } func (b *spongeBatch) Reset() {} func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil } -// TestCommitSequence tests that the trie.Commit operation writes the elements of the trie -// in the expected order. -// The test data was based on the 'master' code, and is basically random. It can be used -// to check whether changes to the trie modifies the write order or data in any way. +// TestCommitSequence tests that the trie.Commit operation writes the elements +// of the trie in the expected order. +// +// The test data was based on the 'master' code, and is basically random. +// It can be used to check whether changes to the trie modifies the write order +// or data in any way. func TestCommitSequence(t *testing.T) { for i, tc := range []struct { count int @@ -887,19 +896,23 @@ func TestCommitSequence(t *testing.T) { {2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")}, } { addresses, accounts := makeAccounts(tc.count) + // This spongeDb is used to check the sequence of disk-db-writes s := &spongeDb{sponge: crypto.NewKeccakState()} db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) - trie := NewEmpty(db) + // Fill the trie with elements + trie := NewEmpty(db) for i := 0; i < tc.count; i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) } // Flush trie -> database root, nodes := trie.Commit(false) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + // Flush memdb -> disk (sponge) db.Commit(root) + if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) } @@ -917,12 +930,13 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { {200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")}, {2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")}, } { - prng := rand.New(rand.NewSource(int64(i))) // This spongeDb is used to check the sequence of disk-db-writes + prng := rand.New(rand.NewSource(int64(i))) s := &spongeDb{sponge: crypto.NewKeccakState()} db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) - trie := NewEmpty(db) + // Fill the trie with elements + trie := NewEmpty(db) for i := 0; i < tc.count; i++ { key := make([]byte, 32) var val []byte @@ -939,6 +953,7 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { // Flush trie -> database root, nodes := trie.Commit(false) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + // Flush memdb -> disk (sponge) db.Commit(root) if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { @@ -974,19 +989,22 @@ func TestCommitSequenceStackTrie(t *testing.T) { // For the stack trie, we need to do inserts in proper order key := make([]byte, 32) binary.BigEndian.PutUint64(key, uint64(i)) - var val []byte + // 50% short elements, 50% large elements + var val []byte if prng.Intn(2) == 0 { val = make([]byte, 1+prng.Intn(32)) } else { val = make([]byte, 1+prng.Intn(1024)) } prng.Read(val) + trie.Update(key, val) stTrie.Update(key, val) } // Flush trie -> database root, nodes := trie.Commit(false) + // Flush memdb -> disk (sponge) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Commit(root) @@ -1045,6 +1063,7 @@ func TestCommitSequenceSmallRoot(t *testing.T) { // Flush trie -> database root, nodes := trie.Commit(false) + // Flush memdb -> disk (sponge) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Commit(root) From 68d477670c562747ba670523b14379506eecb112 Mon Sep 17 00:00:00 2001 From: piersy Date: Tue, 18 Feb 2025 05:50:19 +0000 Subject: [PATCH 22/47] utils: clarify description for history.state flag (#31164) --- cmd/utils/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f079df83b9..243b5d22f0 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -262,7 +262,7 @@ var ( } StateHistoryFlag = &cli.Uint64Flag{ Name: "history.state", - Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)", + Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)", Value: ethconfig.Defaults.StateHistory, Category: flags.StateCategory, } From 7332a1bc0ae14d25333d697a6a7a97b159928efb Mon Sep 17 00:00:00 2001 From: EdisonSR <61781882@qq.com> Date: Tue, 18 Feb 2025 18:15:36 +0800 Subject: [PATCH 23/47] ethclient: add comment describing block number tags (#30984) Adds a comment on how to use rpc.*BlockNumber and the explanation of the block number tags --------- Co-authored-by: Gary Rong --- ethclient/ethclient.go | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index f10626c01f..c761d4f8d3 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -85,11 +85,23 @@ func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) } -// BlockByNumber returns a block from the current canonical chain. If number is nil, the -// latest known block is returned. +// BlockByNumber returns a block from the current canonical chain. +// If `number` is nil, the latest known block is returned. // -// Note that loading full blocks requires two requests. Use HeaderByNumber -// if you don't need all transactions or uncle headers. +// Use `HeaderByNumber` if you don't need full transaction data or uncle headers. +// +// Supported special block number tags: +// - `earliest` : The genesis (earliest) block +// - `latest` : The most recently included block +// - `safe` : The latest safe head block +// - `finalized` : The latest finalized block +// - `pending` : The pending block +// +// Example usage: +// +// ```go +// BlockByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber))) +// ``` func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true) } @@ -210,8 +222,21 @@ func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.He return head, err } -// HeaderByNumber returns a block header from the current canonical chain. If number is -// nil, the latest known header is returned. +// HeaderByNumber returns a block header from the current canonical chain. +// If `number` is nil, the latest known block header is returned. +// +// Supported special block number tags: +// - `earliest` : The genesis (earliest) block +// - `latest` : The most recently included block +// - `safe` : The latest safe head block +// - `finalized` : The latest finalized block +// - `pending` : The pending block +// +// Example usage: +// +// ```go +// HeaderByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber))) +// ``` func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { var head *types.Header err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) From 32c6aa8a1a2595cbb89b05f93440d230841f8431 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Tue, 18 Feb 2025 21:53:33 +0800 Subject: [PATCH 24/47] core/vm: clean up EVM environmental structure (#31061) This PR does a few things including: - Remove `ContractRef` interface - Remove `vm.AccountRef` which implements `ContractRef` interface - Maintain the `jumpDests` struct in EVM for sharing between call frames - Simplify the delegateCall context initialization --- core/state_processor.go | 6 +- core/state_transition.go | 5 +- core/vm/contract.go | 86 +++++--------------- core/vm/eips.go | 8 +- core/vm/evm.go | 130 ++++++++++++++---------------- core/vm/gas_table_test.go | 4 +- core/vm/instructions.go | 12 +-- core/vm/instructions_test.go | 11 +-- core/vm/interface.go | 15 ---- core/vm/interpreter_test.go | 2 +- core/vm/runtime/runtime.go | 13 ++- eth/tracers/js/tracer_test.go | 19 +---- eth/tracers/logger/logger_test.go | 18 +---- tests/state_test.go | 5 +- 14 files changed, 109 insertions(+), 225 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 2c74f6f407..4e365c6550 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -229,7 +229,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) { } evm.SetTxContext(NewEVMTxContext(msg)) evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress) - _, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) + _, _, _ = evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560) evm.StateDB.Finalise(true) } @@ -253,7 +253,7 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) { } evm.SetTxContext(NewEVMTxContext(msg)) evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress) - _, _, err := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) + _, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560) if err != nil { panic(err) } @@ -292,7 +292,7 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte } evm.SetTxContext(NewEVMTxContext(msg)) evm.StateDB.AddAddressToAccessList(addr) - ret, _, _ := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) + ret, _, _ := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560) evm.StateDB.Finalise(true) if len(ret) == 0 { return // skip empty output diff --git a/core/state_transition.go b/core/state_transition.go index e7edd76ced..0f9ee9eea5 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -423,7 +423,6 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { var ( msg = st.msg - sender = vm.AccountRef(msg.From) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) contractCreation = msg.To == nil floorDataGas uint64 @@ -484,7 +483,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { vmerr error // vm errors do not effect consensus and are therefore not assigned to err ) if contractCreation { - ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) + ret, _, st.gasRemaining, vmerr = st.evm.Create(msg.From, msg.Data, st.gasRemaining, value) } else { // Increment the nonce for the next transaction. st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall) @@ -507,7 +506,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { } // Execute the transaction's call. - ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value) + ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value) } // Compute refund counter, capped to a refund quotient. diff --git a/core/vm/contract.go b/core/vm/contract.go index 5670244e17..0eaa91d959 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -22,39 +22,20 @@ import ( "github.com/holiman/uint256" ) -// ContractRef is a reference to the contract's backing object -type ContractRef interface { - Address() common.Address -} - -// AccountRef implements ContractRef. -// -// Account references are used during EVM initialisation and -// its primary use is to fetch addresses. Removing this object -// proves difficult because of the cached jump destinations which -// are fetched from the parent contract (i.e. the caller), which -// is a ContractRef. -type AccountRef common.Address - -// Address casts AccountRef to an Address -func (ar AccountRef) Address() common.Address { return (common.Address)(ar) } - // Contract represents an ethereum contract in the state database. It contains // the contract code, calling arguments. Contract implements ContractRef type Contract struct { - // CallerAddress is the result of the caller which initialised this - // contract. However when the "call method" is delegated this value - // needs to be initialised to that of the caller's caller. - CallerAddress common.Address - caller ContractRef - self ContractRef + // caller is the result of the caller which initialised this + // contract. However, when the "call method" is delegated this + // value needs to be initialised to that of the caller's caller. + caller common.Address + address common.Address jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. analysis bitvec // Locally cached result of JUMPDEST analysis Code []byte CodeHash common.Hash - CodeAddr *common.Address Input []byte // is the execution frame represented by this object a contract deployment @@ -66,23 +47,18 @@ type Contract struct { } // NewContract returns a new contract environment for the execution of EVM. -func NewContract(caller ContractRef, object ContractRef, value *uint256.Int, gas uint64) *Contract { - c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object} - - if parent, ok := caller.(*Contract); ok { - // Reuse JUMPDEST analysis from parent context if available. - c.jumpdests = parent.jumpdests - } else { - c.jumpdests = make(map[common.Hash]bitvec) +func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests map[common.Hash]bitvec) *Contract { + // Initialize the jump analysis map if it's nil, mostly for tests + if jumpDests == nil { + jumpDests = make(map[common.Hash]bitvec) + } + return &Contract{ + caller: caller, + address: address, + jumpdests: jumpDests, + Gas: gas, + value: value, } - - // Gas should be a pointer so it can safely be reduced through the run - // This pointer will be off the state transition - c.Gas = gas - // ensures a value is set - c.value = value - - return c } func (c *Contract) validJumpdest(dest *uint256.Int) bool { @@ -132,18 +108,6 @@ func (c *Contract) isCode(udest uint64) bool { return c.analysis.codeSegment(udest) } -// AsDelegate sets the contract to be a delegate call and returns the current -// contract (for chaining calls) -func (c *Contract) AsDelegate() *Contract { - // NOTE: caller must, at all times be a contract. It should never happen - // that caller is something other than a Contract. - parent := c.caller.(*Contract) - c.CallerAddress = parent.CallerAddress - c.value = parent.value - - return c -} - // GetOp returns the n'th element in the contract's byte array func (c *Contract) GetOp(n uint64) OpCode { if n < uint64(len(c.Code)) { @@ -158,7 +122,7 @@ func (c *Contract) GetOp(n uint64) OpCode { // Caller will recursively call caller when the contract is a delegate // call, including that of caller's caller. func (c *Contract) Caller() common.Address { - return c.CallerAddress + return c.caller } // UseGas attempts the use gas and subtracts it and returns true on success @@ -186,7 +150,7 @@ func (c *Contract) RefundGas(gas uint64, logger *tracing.Hooks, reason tracing.G // Address returns the contracts address func (c *Contract) Address() common.Address { - return c.self.Address() + return c.address } // Value returns the contract's value (sent to it from it's caller) @@ -194,18 +158,8 @@ func (c *Contract) Value() *uint256.Int { return c.value } -// SetCallCode sets the code of the contract and address of the backing data -// object -func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) { +// SetCallCode sets the code of the contract, +func (c *Contract) SetCallCode(hash common.Hash, code []byte) { c.Code = code c.CodeHash = hash - c.CodeAddr = addr -} - -// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash. -// In case hash is not provided, the jumpdest analysis will not be saved to the parent context -func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) { - c.Code = codeAndHash.code - c.CodeHash = codeAndHash.hash - c.CodeAddr = addr } diff --git a/core/vm/eips.go b/core/vm/eips.go index 515999bd19..6159eade7e 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -338,13 +338,9 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC } addr := common.Address(a.Bytes20()) code := interpreter.evm.StateDB.GetCode(addr) - contract := &Contract{ - Code: code, - self: AccountRef(addr), - } paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64()) - if !contract.IsSystemCall { - statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false) + if !scope.Contract.IsSystemCall { + statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false) if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) { scope.Contract.Gas = 0 return nil, ErrOutOfGas diff --git a/core/vm/evm.go b/core/vm/evm.go index 442441e9ae..c28dcb2554 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -91,29 +91,40 @@ type EVM struct { // Context provides auxiliary blockchain related information Context BlockContext TxContext + // StateDB gives access to the underlying state StateDB StateDB - // Depth is the current call stack + + // depth is the current call stack depth int // chainConfig contains information about the current chain chainConfig *params.ChainConfig + // chain rules contains the chain rules for the current epoch chainRules params.Rules - // virtual machine configuration options used to initialise the - // evm. + + // virtual machine configuration options used to initialise the evm Config Config - // global (to this context) ethereum virtual machine - // used throughout the execution of the tx. + + // global (to this context) ethereum virtual machine used throughout + // the execution of the tx interpreter *EVMInterpreter + // abort is used to abort the EVM calling operations abort atomic.Bool + // callGasTemp holds the gas available for the current call. This is needed because the // available gas is calculated in gasCall* according to the 63/64 rule and later // applied in opCall*. callGasTemp uint64 + // precompiles holds the precompiled contracts for the current epoch precompiles map[common.Address]PrecompiledContract + + // jumpDests is the aggregated result of JUMPDEST analysis made through + // the life cycle of EVM. + jumpDests map[common.Hash]bitvec } // NewEVM constructs an EVM instance with the supplied block context, state @@ -127,6 +138,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon Config: config, chainConfig: chainConfig, chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), + jumpDests: make(map[common.Hash]bitvec), } evm.precompiles = activePrecompiledContracts(evm.chainRules) evm.interpreter = NewEVMInterpreter(evm) @@ -165,18 +177,18 @@ func (evm *EVM) Interpreter() *EVMInterpreter { return evm.interpreter } -func isSystemCall(caller ContractRef) bool { - return caller.Address() == params.SystemAddress +func isSystemCall(caller common.Address) bool { + return caller == params.SystemAddress } // Call executes the contract associated with the addr with the given input as // parameters. It also handles any necessary value transfer required and takse // the necessary steps to create accounts and reverses the state in case of an // execution error or failed value transfer. -func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { +func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { // Capture the tracer start/end events in debug mode if evm.Config.Tracer != nil { - evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig()) + evm.captureBegin(evm.depth, CALL, caller, addr, input, gas, value.ToBig()) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -186,7 +198,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrDepth } // Fail if we're trying to transfer more than the available balance - if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) { return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() @@ -209,23 +221,20 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } evm.StateDB.CreateAccount(addr) } - evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) + evm.Context.Transfer(evm.StateDB, caller, addr, value) if isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { // Initialise a new contract and set the code that is to be used by the EVM. - // The contract is a scoped environment for this execution context only. code := evm.resolveCode(addr) if len(code) == 0 { ret, err = nil, nil // gas is unchanged } else { - addrCopy := addr - // If the account has no code, we can abort here - // The depth-check is already done, and precompiles handled above - contract := NewContract(caller, AccountRef(addrCopy), value, gas) + // The contract is a scoped environment for this execution context only. + contract := NewContract(caller, addr, value, gas, evm.jumpDests) contract.IsSystemCall = isSystemCall(caller) - contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code) + contract.SetCallCode(evm.resolveCodeHash(addr), code) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -256,10 +265,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // // CallCode differs from Call in the sense that it executes the given address' // code with the caller as context. -func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { +func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { // Invoke tracer hooks that signal entering/exiting a call frame if evm.Config.Tracer != nil { - evm.captureBegin(evm.depth, CALLCODE, caller.Address(), addr, input, gas, value.ToBig()) + evm.captureBegin(evm.depth, CALLCODE, caller, addr, input, gas, value.ToBig()) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -272,7 +281,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // Note although it's noop to transfer X ether to caller itself. But // if caller doesn't have enough balance, it would be an error to allow // over-charging itself. So the check here is necessary. - if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + if !evm.Context.CanTransfer(evm.StateDB, caller, value) { return nil, gas, ErrInsufficientBalance } var snapshot = evm.StateDB.Snapshot() @@ -281,11 +290,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { - addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. - contract := NewContract(caller, AccountRef(caller.Address()), value, gas) - contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) + contract := NewContract(caller, caller, value, gas, evm.jumpDests) + contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -295,7 +303,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } - gas = 0 } } @@ -307,14 +314,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // // DelegateCall differs from CallCode in the sense that it executes the given address' // code with the caller as context and the caller is set to the caller of the caller. -func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { +func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { // Invoke tracer hooks that signal entering/exiting a call frame if evm.Config.Tracer != nil { - // NOTE: caller must, at all times be a contract. It should never happen - // that caller is something other than a Contract. - parent := caller.(*Contract) // DELEGATECALL inherits value from parent call - evm.captureBegin(evm.depth, DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig()) + evm.captureBegin(evm.depth, DELEGATECALL, caller, addr, input, gas, value.ToBig()) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -329,10 +333,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { - addrCopy := addr // Initialise a new contract and make initialise the delegate values - contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() - contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) + // + // Note: The value refers to the original value from the parent call. + contract := NewContract(originCaller, caller, value, gas, evm.jumpDests) + contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -352,10 +357,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by // as parameters while disallowing any modifications to the state during the call. // Opcodes that attempt to perform such modifications will result in exceptions // instead of performing the modifications. -func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { +func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { // Invoke tracer hooks that signal entering/exiting a call frame if evm.Config.Tracer != nil { - evm.captureBegin(evm.depth, STATICCALL, caller.Address(), addr, input, gas, nil) + evm.captureBegin(evm.depth, STATICCALL, caller, addr, input, gas, nil) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -380,14 +385,11 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { - // At this point, we use a copy of address. If we don't, the go compiler will - // leak the 'contract' to the outer scope, and make allocation for 'contract' - // even if the actual execution ends on RunPrecompiled above. - addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. - contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) - contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) + contract := NewContract(caller, addr, new(uint256.Int), gas, evm.jumpDests) + contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) + // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in Homestead this also counts for code storage gas errors. @@ -407,22 +409,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte return ret, gas, err } -type codeAndHash struct { - code []byte - hash common.Hash -} - -func (c *codeAndHash) Hash() common.Hash { - if c.hash == (common.Hash{}) { - c.hash = crypto.Keccak256Hash(c.code) - } - return c.hash -} - // create creates a new contract using code as deployment code. -func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { +func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { if evm.Config.Tracer != nil { - evm.captureBegin(evm.depth, typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig()) + evm.captureBegin(evm.depth, typ, caller, address, code, gas, value.ToBig()) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -432,14 +422,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if evm.depth > int(params.CallCreateDepth) { return nil, common.Address{}, gas, ErrDepth } - if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + if !evm.Context.CanTransfer(evm.StateDB, caller, value) { return nil, common.Address{}, gas, ErrInsufficientBalance } - nonce := evm.StateDB.GetNonce(caller.Address()) + nonce := evm.StateDB.GetNonce(caller) if nonce+1 < nonce { return nil, common.Address{}, gas, ErrNonceUintOverflow } - evm.StateDB.SetNonce(caller.Address(), nonce+1, tracing.NonceChangeContractCreator) + evm.StateDB.SetNonce(caller, nonce+1, tracing.NonceChangeContractCreator) // Charge the contract creation init gas in verkle mode if evm.chainRules.IsEIP4762 { @@ -500,15 +490,18 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } gas = gas - statelessGas } - evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) + evm.Context.Transfer(evm.StateDB, caller, address, value) // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. - contract := NewContract(caller, AccountRef(address), value, gas) - contract.SetCodeOptionalHash(&address, codeAndHash) + contract := NewContract(caller, address, value, gas, evm.jumpDests) + + // Explicitly set the code to a null hash to prevent caching of jump analysis + // for the initialization code. + contract.SetCallCode(common.Hash{}, code) contract.IsDeployment = true - ret, err = evm.initNewContract(contract, address, value) + ret, err = evm.initNewContract(contract, address) if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { @@ -520,7 +513,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, // initNewContract runs a new contract's creation code, performs checks on the // resulting code that is to be deployed, and consumes necessary gas. -func (evm *EVM) initNewContract(contract *Contract, address common.Address, value *uint256.Int) ([]byte, error) { +func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]byte, error) { ret, err := evm.interpreter.Run(contract, nil, false) if err != nil { return ret, err @@ -552,19 +545,18 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address, valu } // Create creates a new contract using code as deployment code. -func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) - return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) +func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + contractAddr = crypto.CreateAddress(caller, evm.StateDB.GetNonce(caller)) + return evm.create(caller, code, gas, value, contractAddr, CREATE) } // Create2 creates a new contract using code as deployment code. // // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. -func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - codeAndHash := &codeAndHash{code: code} - contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) - return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) +func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), crypto.Keccak256(code)) + return evm.create(caller, code, gas, endowment, contractAddr, CREATE2) } // resolveCode returns the code associated with the provided account. After diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index be86885261..cb6143c0b5 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -97,7 +97,7 @@ func TestEIP2200(t *testing.T) { } evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}}) - _, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int)) + _, gas, err := evm.Call(common.Address{}, address, nil, tt.gaspool, new(uint256.Int)) if !errors.Is(err, tt.failure) { t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure) } @@ -153,7 +153,7 @@ func TestCreateGas(t *testing.T) { evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config) var startGas = uint64(testGas) - ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int)) + ret, gas, err := evm.Call(common.Address{}, address, nil, startGas, new(uint256.Int)) if err != nil { return false } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index c9eea33507..1785ffc139 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -677,7 +677,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation) - res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value) + res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract.Address(), input, gas, &value) // Push item on the stack based on the returned error. If the ruleset is // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must @@ -718,7 +718,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation2) // reuse size int for stackvalue stackvalue := size - res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas, + res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract.Address(), input, gas, &endowment, &salt) // Push item on the stack based on the returned error. if suberr != nil { @@ -755,7 +755,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt if !value.IsZero() { gas += params.CallStipend } - ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value) + ret, returnGas, err := interpreter.evm.Call(scope.Contract.Address(), toAddr, args, gas, &value) if err != nil { temp.Clear() @@ -789,7 +789,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ gas += params.CallStipend } - ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, &value) + ret, returnGas, err := interpreter.evm.CallCode(scope.Contract.Address(), toAddr, args, gas, &value) if err != nil { temp.Clear() } else { @@ -818,7 +818,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext // Get arguments from the memory. args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) - ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract, toAddr, args, gas) + ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, gas, scope.Contract.value) if err != nil { temp.Clear() } else { @@ -847,7 +847,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) // Get arguments from the memory. args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) - ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract, toAddr, args, gas) + ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract.Address(), toAddr, args, gas) if err != nil { temp.Clear() } else { diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 08f2b2bfea..0902d17c54 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -49,14 +49,6 @@ var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffff var commonParams []*twoOperandParams var twoOpMethods map[string]executionFunc -type contractRef struct { - addr common.Address -} - -func (c contractRef) Address() common.Address { - return c.addr -} - func init() { // Params is a list of common edgecases that should be used for some common tests params := []string{ @@ -575,8 +567,7 @@ func TestOpTstore(t *testing.T) { mem = NewMemory() caller = common.Address{} to = common.Address{1} - contractRef = contractRef{caller} - contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0) + contract = NewContract(caller, to, new(uint256.Int), 0, nil) scopeContext = ScopeContext{mem, stack, contract} value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") ) diff --git a/core/vm/interface.go b/core/vm/interface.go index 0d7862a66e..57f35cb249 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -17,8 +17,6 @@ package vm import ( - "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/stateless" @@ -104,16 +102,3 @@ type StateDB interface { // Finalise must be invoked at the end of a transaction Finalise(bool) } - -// CallContext provides a basic interface for the EVM calling conventions. The EVM -// depends on this context being implemented for doing subcalls and initialising new EVM contracts. -type CallContext interface { - // Call calls another contract. - Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) - // CallCode takes another contracts code and execute within our own context - CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) - // DelegateCall is same as CallCode except sender and value is propagated from parent to child scope - DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) - // Create creates a new contract - Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) -} diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index cacad8f813..0b93dd59e7 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -53,7 +53,7 @@ func TestLoopInterrupt(t *testing.T) { timeout := make(chan bool) go func(evm *EVM) { - _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int)) + _, _, err := evm.Call(common.Address{}, address, nil, math.MaxUint64, new(uint256.Int)) errChannel <- err }(evm) diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 2243e14b65..9d984291f2 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -128,7 +128,6 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { var ( address = common.BytesToAddress([]byte("contract")) vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) ) if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil { @@ -143,7 +142,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { cfg.State.SetCode(address, code) // Call the code with the given configuration. ret, leftOverGas, err := vmenv.Call( - sender, + cfg.Origin, common.BytesToAddress([]byte("contract")), input, cfg.GasLimit, @@ -166,9 +165,8 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) } var ( - vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) + vmenv = NewEnv(cfg) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) ) if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil { cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin) @@ -179,7 +177,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil) // Call the code with the given configuration. code, address, leftOverGas, err := vmenv.Create( - sender, + cfg.Origin, input, cfg.GasLimit, uint256.MustFromBig(cfg.Value), @@ -200,7 +198,6 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er var ( vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) statedb = cfg.State rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) ) @@ -214,7 +211,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er // Call the code with the given configuration. ret, leftOverGas, err := vmenv.Call( - sender, + cfg.Origin, address, input, cfg.GasLimit, diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index faad1e7194..dbfc7308f7 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -33,19 +33,6 @@ import ( "github.com/holiman/uint256" ) -type account struct{} - -func (account) SubBalance(amount *big.Int) {} -func (account) AddBalance(amount *big.Int) {} -func (account) SetAddress(common.Address) {} -func (account) Value() *big.Int { return nil } -func (account) SetBalance(*uint256.Int) {} -func (account) SetNonce(uint64) {} -func (account) Balance() *uint256.Int { return nil } -func (account) Address() common.Address { return common.Address{} } -func (account) SetCode(common.Hash, []byte) {} -func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} - type dummyStatedb struct { state.StateDB } @@ -68,7 +55,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo gasLimit uint64 = 31000 startGas uint64 = 10000 value = uint256.NewInt(0) - contract = vm.NewContract(account{}, account{}, value, startGas) + contract = vm.NewContract(common.Address{}, common.Address{}, value, startGas, nil) ) evm.SetTxContext(vmctx.txCtx) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} @@ -190,7 +177,7 @@ func TestHaltBetweenSteps(t *testing.T) { t.Fatal(err) } scope := &vm.ScopeContext{ - Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), + Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil), } evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks}) evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)}) @@ -288,7 +275,7 @@ func TestEnterExit(t *testing.T) { t.Fatal(err) } scope := &vm.ScopeContext{ - Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), + Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil), } tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int)) tracer.OnExit(1, []byte{}, 400, nil, false) diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index e7799dde35..b1e38bf627 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -29,22 +29,6 @@ import ( "github.com/holiman/uint256" ) -type dummyContractRef struct { - calledForEach bool -} - -func (dummyContractRef) Address() common.Address { return common.Address{} } -func (dummyContractRef) Value() *big.Int { return new(big.Int) } -func (dummyContractRef) SetCode(common.Hash, []byte) {} -func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) { - d.calledForEach = true -} -func (d *dummyContractRef) SubBalance(amount *big.Int) {} -func (d *dummyContractRef) AddBalance(amount *big.Int) {} -func (d *dummyContractRef) SetBalance(*big.Int) {} -func (d *dummyContractRef) SetNonce(uint64) {} -func (d *dummyContractRef) Balance() *big.Int { return new(big.Int) } - type dummyStatedb struct { state.StateDB } @@ -59,7 +43,7 @@ func TestStoreCapture(t *testing.T) { var ( logger = NewStructLogger(nil) evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()}) - contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000) + contract = vm.NewContract(common.Address{}, common.Address{}, new(uint256.Int), 100000, nil) ) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} var index common.Hash diff --git a/tests/state_test.go b/tests/state_test.go index 0c9553c075..e7525118e2 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -310,8 +310,7 @@ func runBenchmark(b *testing.B, t *StateTest) { evm.SetTxContext(txContext) // Create "contract" for sender to cache code analysis. - sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From), - nil, 0) + sender := vm.NewContract(msg.From, msg.From, nil, 0, nil) var ( gasUsed uint64 @@ -326,7 +325,7 @@ func runBenchmark(b *testing.B, t *StateTest) { start := time.Now() // Execute the message. - _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value)) + _, leftOverGas, err := evm.Call(sender.Address(), *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value)) if err != nil { b.Error(err) return From ef00a6e9a2bcb7b5737808d7e56a5c196009f918 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 18 Feb 2025 15:03:48 +0100 Subject: [PATCH 25/47] params: add osaka blob schedule (#31174) Prevents crashes when running execution spec tests for osaka --- consensus/misc/eip4844/eip4844.go | 8 ++++++++ core/genesis_test.go | 1 + params/config.go | 9 +++++++++ tests/init.go | 10 ++++++++++ 4 files changed, 28 insertions(+) diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go index 4a2754b55c..32b34f4e53 100644 --- a/consensus/misc/eip4844/eip4844.go +++ b/consensus/misc/eip4844/eip4844.go @@ -83,6 +83,8 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int { var frac uint64 switch config.LatestFork(header.Time) { + case forks.Osaka: + frac = config.BlobScheduleConfig.Osaka.UpdateFraction case forks.Prague: frac = config.BlobScheduleConfig.Prague.UpdateFraction case forks.Cancun: @@ -103,6 +105,8 @@ func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int { s = cfg.BlobScheduleConfig ) switch { + case cfg.IsOsaka(london, time) && s.Osaka != nil: + return s.Osaka.Max case cfg.IsPrague(london, time) && s.Prague != nil: return s.Prague.Max case cfg.IsCancun(london, time) && s.Cancun != nil: @@ -125,6 +129,8 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int { return 0 } switch { + case s.Osaka != nil: + return s.Osaka.Max case s.Prague != nil: return s.Prague.Max case s.Cancun != nil: @@ -144,6 +150,8 @@ func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int { s = cfg.BlobScheduleConfig ) switch { + case cfg.IsOsaka(london, time) && s.Osaka != nil: + return s.Osaka.Target case cfg.IsPrague(london, time) && s.Prague != nil: return s.Prague.Target case cfg.IsCancun(london, time) && s.Cancun != nil: diff --git a/core/genesis_test.go b/core/genesis_test.go index ad75afcd9e..86e5617ef8 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -281,6 +281,7 @@ func TestVerkleGenesisCommit(t *testing.T) { BlobScheduleConfig: ¶ms.BlobScheduleConfig{ Cancun: params.DefaultCancunBlobConfig, Prague: params.DefaultPragueBlobConfig, + Osaka: params.DefaultOsakaBlobConfig, Verkle: params.DefaultPragueBlobConfig, }, } diff --git a/params/config.go b/params/config.go index 5a2e10a943..523c987f01 100644 --- a/params/config.go +++ b/params/config.go @@ -317,10 +317,17 @@ var ( Max: 9, UpdateFraction: 5007716, } + // DefaultOsakaBlobConfig is the default blob configuration for the Osaka fork. + DefaultOsakaBlobConfig = &BlobConfig{ + Target: 6, + Max: 9, + UpdateFraction: 5007716, + } // DefaultBlobSchedule is the latest configured blob schedule for test chains. DefaultBlobSchedule = &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, Prague: DefaultPragueBlobConfig, + Osaka: DefaultOsakaBlobConfig, } ) @@ -501,6 +508,7 @@ type BlobConfig struct { type BlobScheduleConfig struct { Cancun *BlobConfig `json:"cancun,omitempty"` Prague *BlobConfig `json:"prague,omitempty"` + Osaka *BlobConfig `json:"osaka,omitempty"` Verkle *BlobConfig `json:"verkle,omitempty"` } @@ -732,6 +740,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { }{ {name: "cancun", timestamp: c.CancunTime, config: bsc.Cancun}, {name: "prague", timestamp: c.PragueTime, config: bsc.Prague}, + {name: "osaka", timestamp: c.OsakaTime, config: bsc.Osaka}, } { if cur.config != nil { if err := cur.config.validate(); err != nil { diff --git a/tests/init.go b/tests/init.go index ee8d354224..a8bc424fa2 100644 --- a/tests/init.go +++ b/tests/init.go @@ -431,6 +431,11 @@ var Forks = map[string]*params.ChainConfig{ PragueTime: u64(0), OsakaTime: u64(0), DepositContractAddress: params.MainnetChainConfig.DepositContractAddress, + BlobScheduleConfig: ¶ms.BlobScheduleConfig{ + Cancun: params.DefaultCancunBlobConfig, + Prague: params.DefaultPragueBlobConfig, + Osaka: params.DefaultOsakaBlobConfig, + }, }, "PragueToOsakaAtTime15k": { ChainID: big.NewInt(1), @@ -453,6 +458,11 @@ var Forks = map[string]*params.ChainConfig{ PragueTime: u64(0), OsakaTime: u64(15_000), DepositContractAddress: params.MainnetChainConfig.DepositContractAddress, + BlobScheduleConfig: ¶ms.BlobScheduleConfig{ + Cancun: params.DefaultCancunBlobConfig, + Prague: params.DefaultPragueBlobConfig, + Osaka: params.DefaultOsakaBlobConfig, + }, }, } From dab746b3efb24954a9d556e910a53fe527846bf4 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Tue, 18 Feb 2025 15:08:43 -0500 Subject: [PATCH 26/47] eth/catalyst: support earlier forks in SimulatedBeacon (#31084) Co-authored-by: Marius van der Wijden --- eth/catalyst/simulated_beacon.go | 54 +++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index a24ff52101..c71add93bc 100644 --- a/eth/catalyst/simulated_beacon.go +++ b/eth/catalyst/simulated_beacon.go @@ -33,6 +33,8 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/params/forks" "github.com/ethereum/go-ethereum/rpc" ) @@ -95,6 +97,16 @@ type SimulatedBeacon struct { lastBlockTime uint64 } +func payloadVersion(config *params.ChainConfig, time uint64) engine.PayloadVersion { + switch config.LatestFork(time) { + case forks.Prague, forks.Cancun: + return engine.PayloadV3 + case forks.Paris, forks.Shanghai: + return engine.PayloadV2 + } + panic("invalid fork, simulated beacon needs to be started post-merge") +} + // NewSimulatedBeacon constructs a new simulated beacon chain. func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) { block := eth.BlockChain().CurrentBlock() @@ -107,7 +119,8 @@ func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, err // if genesis block, send forkchoiceUpdated to trigger transition to PoS if block.Number.Sign() == 0 { - if _, err := engineAPI.ForkchoiceUpdatedV3(current, nil); err != nil { + version := payloadVersion(eth.BlockChain().Config(), block.Time) + if _, err := engineAPI.forkchoiceUpdated(current, nil, version, false); err != nil { return nil, err } } @@ -171,6 +184,8 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u return fmt.Errorf("failed to sync txpool: %w", err) } + version := payloadVersion(c.eth.BlockChain().Config(), timestamp) + var random [32]byte rand.Read(random[:]) fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{ @@ -179,7 +194,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u Withdrawals: withdrawals, Random: random, BeaconRoot: &common.Hash{}, - }, engine.PayloadV3, false) + }, version, false) if err != nil { return err } @@ -204,28 +219,39 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u } } - // Independently calculate the blob hashes from sidecars. - blobHashes := make([]common.Hash, 0) - if envelope.BlobsBundle != nil { - hasher := sha256.New() - for _, commit := range envelope.BlobsBundle.Commitments { - var c kzg4844.Commitment - if len(commit) != len(c) { - return errors.New("invalid commitment length") + var ( + blobHashes []common.Hash + beaconRoot *common.Hash + requests [][]byte + ) + // Compute post-shanghai fields + if version > engine.PayloadV2 { + // Independently calculate the blob hashes from sidecars. + blobHashes = make([]common.Hash, 0) + if envelope.BlobsBundle != nil { + hasher := sha256.New() + for _, commit := range envelope.BlobsBundle.Commitments { + var c kzg4844.Commitment + if len(commit) != len(c) { + return errors.New("invalid commitment length") + } + copy(c[:], commit) + blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c)) } - copy(c[:], commit) - blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c)) } + beaconRoot = &common.Hash{} + requests = envelope.Requests } + // Mark the payload as canon - _, err = c.engineAPI.newPayload(*payload, blobHashes, &common.Hash{}, envelope.Requests, false) + _, err = c.engineAPI.newPayload(*payload, blobHashes, beaconRoot, requests, false) if err != nil { return err } c.setCurrentState(payload.BlockHash, finalizedHash) // Mark the block containing the payload as canonical - if _, err = c.engineAPI.ForkchoiceUpdatedV3(c.curForkchoiceState, nil); err != nil { + if _, err = c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, nil, version, false); err != nil { return err } c.lastBlockTime = payload.Timestamp From 07d7fe2b33c4356d95b045410afbd5bda4abda99 Mon Sep 17 00:00:00 2001 From: levisyin Date: Wed, 19 Feb 2025 18:21:22 +0800 Subject: [PATCH 27/47] build: upgrade -dlgo version to Go 1.24.0 (#31159) Co-authored-by: Felix Lange --- .github/workflows/go.yml | 4 +- .travis.yml | 14 ++-- Dockerfile | 2 +- Dockerfile.alltools | 2 +- build/checksums.txt | 173 ++++++++++++++++++++++----------------- go.mod | 2 +- 6 files changed, 112 insertions(+), 85 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index d1d2579dff..90449ef30d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.23.0 + go-version: 1.24.0 cache: false - name: Run linters @@ -39,7 +39,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.23.0 + go-version: 1.24.0 cache: false - name: Run tests run: go test -short ./... diff --git a/.travis.yml b/.travis.yml index 8953450e84..5e8a493d03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ jobs: os: linux arch: amd64 dist: focal - go: 1.23.x + go: 1.24.x env: - docker services: @@ -33,7 +33,7 @@ jobs: os: linux dist: focal sudo: required - go: 1.23.x + go: 1.24.x env: - azure-linux git: @@ -85,7 +85,7 @@ jobs: os: linux arch: amd64 dist: focal - go: 1.23.x + go: 1.24.x script: - travis_wait 45 go run build/ci.go test $TEST_PACKAGES @@ -93,7 +93,7 @@ jobs: if: type = push os: linux dist: focal - go: 1.22.x + go: 1.23.x script: - travis_wait 45 go run build/ci.go test $TEST_PACKAGES @@ -102,7 +102,7 @@ jobs: if: type = cron || (type = push && tag ~= /^v[0-9]/) os: linux dist: focal - go: 1.23.x + go: 1.24.x env: - ubuntu-ppa git: @@ -118,7 +118,7 @@ jobs: if: type = cron os: linux dist: focal - go: 1.23.x + go: 1.24.x env: - azure-purge git: @@ -131,7 +131,7 @@ jobs: if: type = cron os: linux dist: focal - go: 1.23.x + go: 1.24.x env: - racetests script: diff --git a/Dockerfile b/Dockerfile index ff89e92f25..9b70e9e8a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG VERSION="" ARG BUILDNUM="" # Build Geth in a stock Go builder container -FROM golang:1.23-alpine AS builder +FROM golang:1.24-alpine AS builder RUN apk add --no-cache gcc musl-dev linux-headers git diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 44d5065af0..ac9303c678 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -4,7 +4,7 @@ ARG VERSION="" ARG BUILDNUM="" # Build Geth in a stock Go builder container -FROM golang:1.23-alpine AS builder +FROM golang:1.24-alpine AS builder RUN apk add --no-cache gcc musl-dev linux-headers git diff --git a/build/checksums.txt b/build/checksums.txt index 76f05e5b63..1646cc6c45 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -5,82 +5,109 @@ # https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/fixtures_pectra-devnet-6.tar.gz b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz -# version:golang 1.23.6 +# version:golang 1.24.0 # https://go.dev/dl/ -039c5b04e65279daceee8a6f71e70bd05cf5b801782b6f77c6e19e2ed0511222 go1.23.6.src.tar.gz -adec10f4ba56591f523aa04851f7f6900b1c61508dfa6b80e62717a8e6684a5c go1.23.6.aix-ppc64.tar.gz -782da50ce8ec5e98fac2cd3cdc6a1d7130d093294fc310038f651444232a3fb0 go1.23.6.darwin-amd64.tar.gz -5cae2450a1708aeb0333237a155640d5562abaf195defebc4306054565536221 go1.23.6.darwin-arm64.tar.gz -d52efb3020d9332477ade98163c03d2f2fe3e051b0e7e01f0e167412c66de0cb go1.23.6.dragonfly-amd64.tar.gz -d3287706b5823712ac6cf7dff684a556cff98163ef60e7b275abe3388c17aac7 go1.23.6.freebsd-386.tar.gz -ebb4c6a9b0673dbdabc439877779ed6add16575e21bd0a7955c33f692789aef6 go1.23.6.freebsd-amd64.tar.gz -b7241584afb0b161c09148f8fde16171bb743e47b99d451fbc5f5217ec7a88b6 go1.23.6.freebsd-arm.tar.gz -004718b53cedd7955d1b1dc4053539fcd1053c031f5f3374334a22befd1f8310 go1.23.6.freebsd-arm64.tar.gz -ca026ec8a30dd0c18164f40e1ce21bd725e2445f11699177d05815189a38de7a go1.23.6.freebsd-riscv64.tar.gz -7db973efa3fb2e48e45059b855721550fce8e90803e7373d3efd37b88dd821e8 go1.23.6.illumos-amd64.tar.gz -e61f87693169c0bbcc43363128f1e929b9dff0b7f448573f1bdd4e4a0b9687ba go1.23.6.linux-386.tar.gz -9379441ea310de000f33a4dc767bd966e72ab2826270e038e78b2c53c2e7802d go1.23.6.linux-amd64.tar.gz -561c780e8f4a8955d32bf72e46af0b5ee5e0debe1e4633df9a03781878219202 go1.23.6.linux-arm64.tar.gz -27a4611010c16b8c4f37ade3aada55bd5781998f02f348b164302fd5eea4eb74 go1.23.6.linux-armv6l.tar.gz -c459226424372abc2b35957cc8955dad348330714f7605093325dbb73e33c750 go1.23.6.linux-loong64.tar.gz -e2a0aff70b958a3463a7d47132a2d0238369f64578d4f7f95e679e3a5af05622 go1.23.6.linux-mips.tar.gz -7d30ec7db056311d420bf930c16abcae13c0f41c26a202868f279721ec3c2f2f go1.23.6.linux-mips64.tar.gz -74ca7bc475bcc084c6718b74df024d7de9612932cea8a6dc75e29d3a5315a23a go1.23.6.linux-mips64le.tar.gz -09bf935a14e9f59a20499989438b1655453480016bdbcb10406acf4df2678ccb go1.23.6.linux-mipsle.tar.gz -5cb2f6a5090276c72c5eda8a55896f5a3d6ea0f28d10fa1a50e8318640f02d6c go1.23.6.linux-ppc64.tar.gz -0f817201e83d78ddbfa27f5f78d9b72450b92cc21d5e045145efacd0d3244a99 go1.23.6.linux-ppc64le.tar.gz -f95f7f817ab22ecab4503d0704d6449ea1aa26a595f57bf9b9f94ddf2aa7c1f3 go1.23.6.linux-riscv64.tar.gz -321e7ed0d5416f731479c52fa7610b52b8079a8061967bd48cec6d66f671a60e go1.23.6.linux-s390x.tar.gz -92d678fb8e1eeeb8c6af6f22e4e5494652dcbb4a320113fc08325cb9956a2d4c go1.23.6.netbsd-386.tar.gz -86ba51e7bb26b30ea6a8d88ddb79d8e8c83b4116200040ecb7a5a44cf90a8c5c go1.23.6.netbsd-amd64.tar.gz -4b974c35345100f0be6ea66afab2781de91ee9882117314126eaf0ae90fd3816 go1.23.6.netbsd-arm.tar.gz -53e3589fc38e787a493ea038961f8e40803714dbb42754c1713b00099c12e9b9 go1.23.6.netbsd-arm64.tar.gz -6d2317b3a8505ccebff8f72d943f2ac9b82c115632e54a53a786eff24ced56d9 go1.23.6.openbsd-386.tar.gz -f699e707d95a984fcc00361d91aecdb413d3c75e18235156ffba7a89edf68aae go1.23.6.openbsd-amd64.tar.gz -3c1cf6ab893657d0bf1942e40ce115acfd27cbce1ccb9bc88fd9cd21ca3d489f go1.23.6.openbsd-arm.tar.gz -cc0875535d14001f2da23ae9af89025b28c466e8f4f4c63f991ebb6f4b02f66c go1.23.6.openbsd-arm64.tar.gz -64de80e29ca66cb566cbf8be030bf8599953af4e48402eab724cbe0a08b40602 go1.23.6.openbsd-ppc64.tar.gz -c398a6b43c569f34bb4a2d16b52f8010eaac9a2a82ecac0602b4338e35cef377 go1.23.6.openbsd-riscv64.tar.gz -10998b6b130bb7b542b407f0db42b86a913b111f8fa86d44394beaace4d45f01 go1.23.6.plan9-386.tar.gz -9fbe8065436d8d12c02f19f64f51c9107da3a7a4ac46ab5777e182e9fe88c32f go1.23.6.plan9-amd64.tar.gz -8e3c826b884daee2de37e3b070d7eac4cea5d68edab8db09910e22201c75db83 go1.23.6.plan9-arm.tar.gz -b619eff63fec86daaea92ca170559e448a58b8ba0b92eef1971bc14e92ea86a7 go1.23.6.solaris-amd64.tar.gz -96820c0f5d464dd694543329e9b4d413b17c821c03a055717a29e6735b44c2d8 go1.23.6.windows-386.zip -53fec1586850b2cf5ad6438341ff7adc5f6700dd3ec1cfa3f5e8b141df190243 go1.23.6.windows-amd64.zip -22c2518c45c20018afa20d5376dc9fd7a7e74367240ed7b5209e79a30b5c4218 go1.23.6.windows-arm.zip -a2d2ec1b3759552bdd9cdf58858f91dfbfd6ab3a472f00b5255acbed30b1aa41 go1.23.6.windows-arm64.zip +d14120614acb29d12bcab72bd689f257eb4be9e0b6f88a8fb7e41ac65f8556e5 go1.24.0.src.tar.gz +5d04588154d5923bd8e26b76111806340ec55c41af1b05623ea744fcb3d6bc22 go1.24.0.aix-ppc64.tar.gz +7af054e5088b68c24b3d6e135e5ca8d91bbd5a05cb7f7f0187367b3e6e9e05ee go1.24.0.darwin-amd64.tar.gz +dee0ea64411a00b47ded586d5a8e30cfe3acf51564aa1bb24e039a6dca807a29 go1.24.0.darwin-amd64.pkg +fd9cfb5dd6c75a347cfc641a253f0db1cebaca16b0dd37965351c6184ba595e4 go1.24.0.darwin-arm64.tar.gz +b19eb6b7ae87f8371c3e7a84d129db67779a2883d2fffa6bb90412b0167df133 go1.24.0.darwin-arm64.pkg +d0dc34ad86aea746abe245994c68a9e1ad8f46ba8c4af901cd5861a4dd4c21df go1.24.0.dragonfly-amd64.tar.gz +4ee02b1f3812aff4da79c79464ee4038ca61ad74b3a9619850f30435f81c2536 go1.24.0.freebsd-386.tar.gz +838191001f9324da904dece35a586a3156d548687db87ac9461aa3d38fc88b09 go1.24.0.freebsd-amd64.tar.gz +ce6ad4e84a40a8a1d848b7e31b0cddfd1cee8f7959e7dc358a8fa8b5566ea718 go1.24.0.freebsd-arm.tar.gz +511f7b0cac4c4ed1066d324072ce223b906ad6b2a85f2e1c5d260eb7d08b5901 go1.24.0.freebsd-arm64.tar.gz +a1e4072630dc589a2975ef51317b52c7d8599bf6f389fc59033c01e0a0fa705a go1.24.0.freebsd-riscv64.tar.gz +7593e9dcee9f07c3df6d099f7d259f5734a6c0dccc5f28962f18e7f501c9bb21 go1.24.0.illumos-amd64.tar.gz +90521453a59c6ce20364d2dc7c38532949b033b602ba12d782caeb90af1b0624 go1.24.0.linux-386.tar.gz +dea9ca38a0b852a74e81c26134671af7c0fbe65d81b0dc1c5bfe22cf7d4c8858 go1.24.0.linux-amd64.tar.gz +c3fa6d16ffa261091a5617145553c71d21435ce547e44cc6dfb7470865527cc7 go1.24.0.linux-arm64.tar.gz +695dc54fa14cd3124fa6900d7b5ae39eeac23f7a4ecea81656070160fac2c54a go1.24.0.linux-armv6l.tar.gz +a201e4c9b7e6d29ed64c43296ed88e81a66f82f2093ce45b766d2c526941396f go1.24.0.linux-loong64.tar.gz +f3ac039aae78ad0bfb08106406c2e62eaf763dd82ebaf0ecd539adadd1d729a6 go1.24.0.linux-mips.tar.gz +f2e6456d45e024831b1da8d88b1bb6392cca9500c1b00841f525d76c9e9553e0 go1.24.0.linux-mips64.tar.gz +b847893ff119389c939adc2b8516b6500204b7cb49d5e19b25e1c2091d2c74c6 go1.24.0.linux-mips64le.tar.gz +bd4aed27d02746c237c3921e97029ac6b6fe687a67436b8f52ff1f698d330bd9 go1.24.0.linux-mipsle.tar.gz +007123c9b06c41729a4bb3f166f4df7196adf4e33c2d2ab0e7e990175f0ce1d4 go1.24.0.linux-ppc64.tar.gz +a871a43de7d26c91dd90cb6e0adacb214c9e35ee2188c617c91c08c017efe81a go1.24.0.linux-ppc64le.tar.gz +620dcf48c6297519aad6c81f8e344926dc0ab09a2a79f1e306964aece95a553d go1.24.0.linux-riscv64.tar.gz +544d78b077c6b54bf78958c4a8285abec2d21f668fb007261c77418cd2edbb46 go1.24.0.linux-s390x.tar.gz +8b143a7edefbaa2a0b0246c9df2df1bac9fbed909d8615a375c08da7744e697d go1.24.0.netbsd-386.tar.gz +67150a6dd7bdb9c4e88d77f46ee8c4dc99d5e71deca4912d8c2c85f7a16d0262 go1.24.0.netbsd-amd64.tar.gz +446b2539f11218fd6f6f6e3dd90b20ae55a06afe129885eeb3df51eb344eb0f6 go1.24.0.netbsd-arm.tar.gz +370115b6ff7d30b29431223de348eb11ab65e3c92627532d97fd55f63f94e7a8 go1.24.0.netbsd-arm64.tar.gz +cbda5f15f06ed9630f122a53542d9de13d149643633c74f1dcb45e79649b788a go1.24.0.openbsd-386.tar.gz +926f601d0e655ab1e8d7f357fd82542e5cf206c38c4e2f9fccf0706987d38836 go1.24.0.openbsd-amd64.tar.gz +8a54892f8c933c541fff144a825d0fdc41bae14b0832aab703cb75eb4cb64f2c go1.24.0.openbsd-arm.tar.gz +ef7fddcef0a22c7900c178b7687cf5aa25c2a9d46a3cc330b77a6de6e6c2396b go1.24.0.openbsd-arm64.tar.gz +b3b5e2e2b53489ded2c2c21900ddcbbdb7991632bb5b42f05f125d71675e0b76 go1.24.0.openbsd-ppc64.tar.gz +fbcb1dbf1269b4079dc4fd0b15f3274b9d635f1a7e319c3fc1a907b03280348e go1.24.0.openbsd-riscv64.tar.gz +33b4221e1c174a16e3f661deab6c60838ac4ae6cb869a4da1d1115773ceed88b go1.24.0.plan9-386.tar.gz +111a89014019cdbd69c2978de9b3e201f77e35183c8ab3606fba339d38f28549 go1.24.0.plan9-amd64.tar.gz +8da3d3997049f40ebe0cd336a9bb9e4bfa4832df3c90a32f07383371d6d74849 go1.24.0.plan9-arm.tar.gz +b6069da21dc95ccdbd047675b584e5480ffc3eba35f9e7c8b0e7b317aaf01e2c go1.24.0.solaris-amd64.tar.gz +b53c28a4c2863ec50ab4a1dbebe818ef6177f86773b6f43475d40a5d9aa4ec9e go1.24.0.windows-386.zip +f07677013cd7861c5e16067b0a82144c23c4bf72c139c762e142440f4c926f61 go1.24.0.windows-386.msi +96b7280979205813759ee6947be7e3bb497da85c482711116c00522e3bb41ff1 go1.24.0.windows-amd64.zip +4e78016d889431eb16aa0f87868cf52479b90059791c94a4ff45872d0573089e go1.24.0.windows-amd64.msi +53f73450fb66075d16be9f206e9177bd972b528168271918c4747903b5596c3d go1.24.0.windows-arm64.zip +4f9780158fb7996dcbcbc7c7ef208f880b5e8c1f2792ba3ede0c75050c1bc23a go1.24.0.windows-arm64.msi -# version:golangci 1.63.4 +# version:golangci 1.64.4 # https://github.com/golangci/golangci-lint/releases/ -# https://github.com/golangci/golangci-lint/releases/download/v1.63.4/ -878d017cc360e4fb19510d39852c8189852e3c48e7ce0337577df73507c97d68 golangci-lint-1.63.4-darwin-amd64.tar.gz -a2b630c2ac8466393f0ccbbede4462387b6c190697a70bc2298c6d2123f21bbf golangci-lint-1.63.4-darwin-arm64.tar.gz -8938b74aa92888e561a1c5a4c175110b92f84e7d24733703e6d9ebc39e9cd5f8 golangci-lint-1.63.4-freebsd-386.tar.gz -054903339d620df2e760b978920100986e3b03bcb058f669d520a71dac9c34ed golangci-lint-1.63.4-freebsd-amd64.tar.gz -a19d499f961a02608348e8b626537a88edfaab6e1b6534f1eff742b5d6d750e4 golangci-lint-1.63.4-freebsd-armv6.tar.gz -00d616f0fb275b780ce4d26604bdd7fdbfe6bc9c63acd5a0b31498e1f7511108 golangci-lint-1.63.4-freebsd-armv7.tar.gz -d453688e0eabded3c1a97ff5a2777bb0df5a18851efdaaaf6b472e3e5713c33e golangci-lint-1.63.4-illumos-amd64.tar.gz -6b1bec847fc9f347d53712d05606a49d55d0e3b5c1bacadfed2393f3503de0e9 golangci-lint-1.63.4-linux-386.tar.gz -01abb14a4df47b5ca585eff3c34b105023cba92ec34ff17212dbb83855581690 golangci-lint-1.63.4-linux-amd64.tar.gz -51f0c79d19a92353e0465fb30a4901a0644a975d34e6f399ad2eebc0160bbb24 golangci-lint-1.63.4-linux-arm64.tar.gz -8d0a43f41e8424fbae10f7aa2dc29999f98112817c6dba63d7dc76832940a673 golangci-lint-1.63.4-linux-armv6.tar.gz -1045a047b31e9302c9160c7b0f199f4ac1bd02a1b221a2d9521bd3507f0cf671 golangci-lint-1.63.4-linux-armv7.tar.gz -933fe10ab50ce3bb0806e15a4ae69fe20f0549abf91dea0161236000ca706e67 golangci-lint-1.63.4-linux-loong64.tar.gz -45798630cbad5642862766051199fa862ef3c33d569cab12f01cac4f68e2ddd5 golangci-lint-1.63.4-linux-mips64.tar.gz -86ae25335ddb24975d2c915c1af0c7fad70dce99d0b4614fa4bee392de714aa2 golangci-lint-1.63.4-linux-mips64le.tar.gz -33dabd11aaba4b602938da98bcf49aabab55019557e0115cdc3dbcc3009768fa golangci-lint-1.63.4-linux-ppc64le.tar.gz -4e7a81230a663bcdf30bba5689ce96040abc76994dbc2003dce32c8dca8c06f3 golangci-lint-1.63.4-linux-riscv64.tar.gz -21370b49c7c47f4d9b8f982c952f940b01e65710174c3b4dad7b6452d58f92ec golangci-lint-1.63.4-linux-s390x.tar.gz -255866a6464c7e11bb7edd8e6e6ad54f11e1f01b82ba9ca229698ac788cd9724 golangci-lint-1.63.4-netbsd-386.tar.gz -2798c040ac658bda97224f204795199c81ac97bb207b21c02b664aaed380d5d2 golangci-lint-1.63.4-netbsd-amd64.tar.gz -b910eecffd0064103837e7e1abe870deb8ade22331e6dffe319f430d49399c8e golangci-lint-1.63.4-netbsd-arm64.tar.gz -df2693ef37147b457c3e2089614537dd2ae2e18e53641e756a5b404f4c72d3fa golangci-lint-1.63.4-netbsd-armv6.tar.gz -a28a533366974bd7834c4516cd6075bff3419a508d1ed7aa63ae8182768b352e golangci-lint-1.63.4-netbsd-armv7.tar.gz -368932775fb5c620b324dabf018155f3365f5e33c5af5b26e9321db373f96eea golangci-lint-1.63.4-windows-386.zip -184d13c2b8f5441576bec2a0d8ba7b2d45445595cf796b879a73bcc98c39f8c1 golangci-lint-1.63.4-windows-amd64.zip -4fabf175d5b05ef0858ded49527948eebac50e9093814979fd84555a75fb80a6 golangci-lint-1.63.4-windows-arm64.zip -e92be3f3ff30d4a849fb4b9a4c8d56837dee45269cb405a3ecad52fa034c781b golangci-lint-1.63.4-windows-armv6.zip -c71d348653b8f7fbb109bb10c1a481722bc6b0b2b6e731b897f99ac869f7653e golangci-lint-1.63.4-windows-armv7.zip +# https://github.com/golangci/golangci-lint/releases/download/v1.64.4/ +f31ef6e20c62acc31eb7b851d611b4bd10256d1b1d8be38f0cceec300b5b60db golangci-lint-1.64.4-darwin-amd64.tar.gz +bb4a9ece7ef66ef49bd6de873f5f5ec801cf93dacf58efb360cc939b4fd37c47 golangci-lint-1.64.4-darwin-arm64.tar.gz +fd8f9046150356e36ad8af31f99219515d5e0ff6e8e9f4204182312447018fcf golangci-lint-1.64.4-freebsd-386.tar.gz +bbae940caa31cb1d2d8d26abd867666cd92746d2ddc63d6917d128c456d715ef golangci-lint-1.64.4-freebsd-amd64.tar.gz +86eb00cbdc5e277857a380d556d78a42b3edf8aae5991de8767dce7da337d73b golangci-lint-1.64.4-freebsd-armv6.tar.gz +c0f7d50f4fcd39ae8bda181c127b078a79d87c885ac472c4cce5b01134dde5bc golangci-lint-1.64.4-freebsd-armv7.tar.gz +31d264fa26a73a583425bc9b39c18de70a330e346fe800e80c277ddb5f8477b6 golangci-lint-1.64.4-illumos-amd64.tar.gz +3dccc18a6b1a0f2518196190ed56277b1480b381231605936eca6b862426b83c golangci-lint-1.64.4-linux-386.deb +b95f3e757c59ada75144bd086478ab63bcda83c2b2a935e60d8f39aff20fbcd2 golangci-lint-1.64.4-linux-386.rpm +8fa58af0022ae0487162c02d08075e2d869c9b5f8613a64b85fd769a2a2d2b93 golangci-lint-1.64.4-linux-386.tar.gz +fa80d2ad920fc74b85a0b93ad1671fd27c9c4d6f22e167cc4e1da758d72dd893 golangci-lint-1.64.4-linux-amd64.deb +8bf2e3c82504a893a12e84ecbc8071f787075d2fdc1ef946deda3d29aae1afad golangci-lint-1.64.4-linux-amd64.rpm +7de8f80a12cd3052610e6be21f08f2220805b1f3e43b3b6ec843f14a12140de2 golangci-lint-1.64.4-linux-amd64.tar.gz +ade222b9ae997a2875e44ed53ca5a129f24944b232132d0a5898f101381d3bfa golangci-lint-1.64.4-linux-arm64.deb +8f9f8617ed0d8b8f62c8dfe69877932c0d85f0d83a9ec3250b04777c7133ada1 golangci-lint-1.64.4-linux-arm64.rpm +debf1f73e71f1dd288957574eab4e7515b1b04c4ac2f127192181da8a42f0e8e golangci-lint-1.64.4-linux-arm64.tar.gz +3f616caa4a16738114ad29076a333c62bb0650fe4846b438c341d235f78ee5aa golangci-lint-1.64.4-linux-armv6.deb +6a7c9d7b7c57d7d440e1e3f133e18e4b5b703604d4ae7f7862fb9ea461887a8b golangci-lint-1.64.4-linux-armv6.rpm +d7b9e3c89af93d98c6b5a555ef48e25bee24f84d7825a29e343e9966404d5b4d golangci-lint-1.64.4-linux-armv6.tar.gz +18179ecf04ace3051450852424b31a4d26644a3912e759cd595e624eee0174bd golangci-lint-1.64.4-linux-armv7.deb +f669fce85d3edc3d557d1e64e2241d895f1ee676f79d139874bf76693cc447a2 golangci-lint-1.64.4-linux-armv7.rpm +9bbaa13b474ecb1560fb05aee0a8cab3e9cc327d41632bee8b553b766f2bf756 golangci-lint-1.64.4-linux-armv7.tar.gz +b5a2725adba2a1b04a5160ffa0730ba30b88c1ee99ecbc65dd7075a8d70f3730 golangci-lint-1.64.4-linux-loong64.deb +28ac00afb3f6407808fe7c15a6002e5fe6b3b461df3fe0223603542e6f9b974a golangci-lint-1.64.4-linux-loong64.rpm +121170309fed82cb64d6fae5020ef2b194e591a53156370c221a80121cc4aa08 golangci-lint-1.64.4-linux-loong64.tar.gz +aadfaab41380f53ada8f7ad4fa9af784bb882eaaa1e3939e048b3a5ea8f2c13f golangci-lint-1.64.4-linux-mips64.deb +6fecbff69086e316dd028050d3ebf82fc466c7f4dc0f6084307054621101c202 golangci-lint-1.64.4-linux-mips64.rpm +430c48034527af028dc608c115166f47b6b67c8cb83a317d9d44876b9753292a golangci-lint-1.64.4-linux-mips64.tar.gz +432126af2bbbd639dbbcc2c265337f104cc613a7b4c5a8fb5e49f182b428f077 golangci-lint-1.64.4-linux-mips64le.deb +cfa663eee0fae721510d6dc31e61db4be51b4e4244eb7de2b6a9bc6d475551e5 golangci-lint-1.64.4-linux-mips64le.rpm +2bacfac65182893c5ceb67b61d5b9d2b24da47726d84cb87d734a6e32f040148 golangci-lint-1.64.4-linux-mips64le.tar.gz +66d86e47d68420c03045eff0698e9acf9f82d97cd1f07d7e52837a6e544eceed golangci-lint-1.64.4-linux-ppc64le.deb +05466bd2d8e82f7245b838e29d0c90cdbaf67375b2b5bc980d8510d5edb206ad golangci-lint-1.64.4-linux-ppc64le.rpm +e013b6980f7140712af0aedc9a661265e1d3c6adc7e9d045734e3686a3601acc golangci-lint-1.64.4-linux-ppc64le.tar.gz +753980d2fb421d35292b71b51f9bb0552f18de2eb181ccf692ef79e086ad2304 golangci-lint-1.64.4-linux-riscv64.deb +73a33a883020298f8c652a4ace4f6888103d80d411fe3e9b77ce0a3b36ff7d3a golangci-lint-1.64.4-linux-riscv64.rpm +020efd09b894dc75012f43b1d4c58e69e5446ca3f79845b5e10a02588def3e1b golangci-lint-1.64.4-linux-riscv64.tar.gz +4d99a16bc9ff5cea5e4ae3568c6254390fbdad8f1d370c287744409112bceff9 golangci-lint-1.64.4-linux-s390x.deb +6e63374a9f95fc09f2bb9501059eb18b8107e08416722ba7b561ae385d80b33b golangci-lint-1.64.4-linux-s390x.rpm +62a6febb892b26eee84a32cc99d04afe90bf62d0970774b1bab75e36b66f53b4 golangci-lint-1.64.4-linux-s390x.tar.gz +5ba4d235f9abd60d2d280f9fe4228c6ddab11ae9fe48d253b7e477046675f1f6 golangci-lint-1.64.4-netbsd-386.tar.gz +061643bb4370a52010e5e76f88f5b5220e51058df50af86b45286263af92b321 golangci-lint-1.64.4-netbsd-amd64.tar.gz +12b2be6c35bcf7a36374e952c7efec7905a17fa3ebe6214924ba8721b766c4af golangci-lint-1.64.4-netbsd-arm64.tar.gz +553a71a677751dccee082ed8afe24cf58bef725f72aa02aedcc6758dd8f44125 golangci-lint-1.64.4-netbsd-armv6.tar.gz +74a5a5a7b8c8cd11dccdec303ee6592d904b09836782e6d658be359737f300ef golangci-lint-1.64.4-netbsd-armv7.tar.gz +b3ceea2187843f9ba6510303141a72465621e3f190a262c0b48707b9e983ea9a golangci-lint-1.64.4-source.tar.gz +fda4de312fcb0b4853b03bcdfb31ac631a68fa0b966f6aa010eb30d14427180b golangci-lint-1.64.4-windows-386.zip +8fc60bd809f86c6431ed8f3d1f25917538c0ebc93e670cfb199f25bbaa56e602 golangci-lint-1.64.4-windows-amd64.zip +b9058c9d2ae8d75048c6ad8885d11e5ac0a6c40be2af85bfa6605e48d69d3eb6 golangci-lint-1.64.4-windows-arm64.zip +809b0131adb1aa8b359becd13222df367b505bc2955bb3b1d2d0dd6f07347b13 golangci-lint-1.64.4-windows-armv6.zip +fc43f8c95d6bec8ba9a3557a0bb63cf9f504137ce6d24cfdc4c330d46f7779d2 golangci-lint-1.64.4-windows-armv7.zip # This is the builder on PPA that will build Go itself (inception-y), don't modify! # diff --git a/go.mod b/go.mod index cf9fda50c8..c9f4a4e4ba 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum/go-ethereum -go 1.22.0 +go 1.23.0 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 From aac621987eda4fabf71f159e24560caf30d0e7de Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 19 Feb 2025 14:57:08 +0100 Subject: [PATCH 28/47] core/asm: delete assembler/disassembler (#31211) I maintain an improved version of the go-ethereum assembler at https://github.com/fjl/geas. We don't really use core/asm in our tests, and it has some bugs that prevent it from being useful, so I'm removing the package. --- core/asm/asm.go | 156 ----------------- core/asm/asm_test.go | 94 ---------- core/asm/compiler.go | 292 -------------------------------- core/asm/compiler_test.go | 79 --------- core/asm/lex_test.go | 93 ---------- core/asm/lexer.go | 275 ------------------------------ core/asm/tokentype_string.go | 31 ---- core/vm/runtime/runtime_test.go | 15 +- 8 files changed, 1 insertion(+), 1034 deletions(-) delete mode 100644 core/asm/asm.go delete mode 100644 core/asm/asm_test.go delete mode 100644 core/asm/compiler.go delete mode 100644 core/asm/compiler_test.go delete mode 100644 core/asm/lex_test.go delete mode 100644 core/asm/lexer.go delete mode 100644 core/asm/tokentype_string.go diff --git a/core/asm/asm.go b/core/asm/asm.go deleted file mode 100644 index f4b59f4471..0000000000 --- a/core/asm/asm.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2017 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 . - -// Package asm provides support for dealing with EVM assembly instructions (e.g., disassembling them). -package asm - -import ( - "encoding/hex" - "fmt" - - "github.com/ethereum/go-ethereum/core/vm" -) - -// Iterator for disassembled EVM instructions -type instructionIterator struct { - code []byte - pc uint64 - arg []byte - op vm.OpCode - error error - started bool - eofEnabled bool -} - -// NewInstructionIterator creates a new instruction iterator. -func NewInstructionIterator(code []byte) *instructionIterator { - it := new(instructionIterator) - it.code = code - return it -} - -// NewEOFInstructionIterator creates a new instruction iterator for EOF-code. -func NewEOFInstructionIterator(code []byte) *instructionIterator { - it := NewInstructionIterator(code) - it.eofEnabled = true - return it -} - -// Next returns true if there is a next instruction and moves on. -func (it *instructionIterator) Next() bool { - if it.error != nil || uint64(len(it.code)) <= it.pc { - // We previously reached an error or the end. - return false - } - - if it.started { - // Since the iteration has been already started we move to the next instruction. - if it.arg != nil { - it.pc += uint64(len(it.arg)) - } - it.pc++ - } else { - // We start the iteration from the first instruction. - it.started = true - } - - if uint64(len(it.code)) <= it.pc { - // We reached the end. - return false - } - it.op = vm.OpCode(it.code[it.pc]) - var a int - if !it.eofEnabled { // Legacy code - if it.op.IsPush() { - a = int(it.op) - int(vm.PUSH0) - } - } else { // EOF code - if it.op == vm.RJUMPV { - // RJUMPV is unique as it has a variable sized operand. The total size is - // determined by the count byte which immediately follows RJUMPV. - maxIndex := int(it.code[it.pc+1]) - a = (maxIndex+1)*2 + 1 - } else { - a = vm.Immediates(it.op) - } - } - if a > 0 { - u := it.pc + 1 + uint64(a) - if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u { - it.error = fmt.Errorf("incomplete instruction at %v", it.pc) - return false - } - it.arg = it.code[it.pc+1 : u] - } else { - it.arg = nil - } - return true -} - -// Error returns any error that may have been encountered. -func (it *instructionIterator) Error() error { - return it.error -} - -// PC returns the PC of the current instruction. -func (it *instructionIterator) PC() uint64 { - return it.pc -} - -// Op returns the opcode of the current instruction. -func (it *instructionIterator) Op() vm.OpCode { - return it.op -} - -// Arg returns the argument of the current instruction. -func (it *instructionIterator) Arg() []byte { - return it.arg -} - -// PrintDisassembled pretty-print all disassembled EVM instructions to stdout. -func PrintDisassembled(code string) error { - script, err := hex.DecodeString(code) - if err != nil { - return err - } - it := NewInstructionIterator(script) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - fmt.Printf("%05x: %v %#x\n", it.PC(), it.Op(), it.Arg()) - } else { - fmt.Printf("%05x: %v\n", it.PC(), it.Op()) - } - } - return it.Error() -} - -// Disassemble returns all disassembled EVM instructions in human-readable format. -func Disassemble(script []byte) ([]string, error) { - instrs := make([]string, 0) - - it := NewInstructionIterator(script) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - instrs = append(instrs, fmt.Sprintf("%05x: %v %#x\n", it.PC(), it.Op(), it.Arg())) - } else { - instrs = append(instrs, fmt.Sprintf("%05x: %v\n", it.PC(), it.Op())) - } - } - if err := it.Error(); err != nil { - return nil, err - } - return instrs, nil -} diff --git a/core/asm/asm_test.go b/core/asm/asm_test.go deleted file mode 100644 index 50fe9e1225..0000000000 --- a/core/asm/asm_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2017 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 . - -package asm - -import ( - "encoding/hex" - "fmt" - "strings" - "testing" -) - -// Tests disassembling instructions -func TestInstructionIterator(t *testing.T) { - for i, tc := range []struct { - code string - legacyWant string - eofWant string - }{ - {"", "", ""}, // empty - {"6100", `err: incomplete instruction at 0`, `err: incomplete instruction at 0`}, - {"61000000", ` -00000: PUSH2 0x0000 -00003: STOP`, ` -00000: PUSH2 0x0000 -00003: STOP`}, - {"5F00", ` -00000: PUSH0 -00001: STOP`, ` -00000: PUSH0 -00001: STOP`}, - {"d1aabb00", `00000: DATALOADN -00001: opcode 0xaa not defined -00002: opcode 0xbb not defined -00003: STOP`, ` -00000: DATALOADN 0xaabb -00003: STOP`}, // DATALOADN(aabb),STOP - {"d1aa", ` -00000: DATALOADN -00001: opcode 0xaa not defined`, "err: incomplete instruction at 0\n"}, // DATALOADN(aa) invalid - {"e20211223344556600", ` -00000: RJUMPV -00001: MUL -00002: GT -00003: opcode 0x22 not defined -00004: CALLER -00005: DIFFICULTY -00006: SSTORE -err: incomplete instruction at 7`, ` -00000: RJUMPV 0x02112233445566 -00008: STOP`}, // RJUMPV( 6 bytes), STOP - - } { - var ( - code, _ = hex.DecodeString(tc.code) - legacy = strings.TrimSpace(disassembly(NewInstructionIterator(code))) - eof = strings.TrimSpace(disassembly(NewEOFInstructionIterator(code))) - ) - if want := strings.TrimSpace(tc.legacyWant); legacy != want { - t.Errorf("test %d: wrong (legacy) output. have:\n%q\nwant:\n%q\n", i, legacy, want) - } - if want := strings.TrimSpace(tc.eofWant); eof != want { - t.Errorf("test %d: wrong (eof) output. have:\n%q\nwant:\n%q\n", i, eof, want) - } - } -} - -func disassembly(it *instructionIterator) string { - var out = new(strings.Builder) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - fmt.Fprintf(out, "%05x: %v %#x\n", it.PC(), it.Op(), it.Arg()) - } else { - fmt.Fprintf(out, "%05x: %v\n", it.PC(), it.Op()) - } - } - if err := it.Error(); err != nil { - fmt.Fprintf(out, "err: %v\n", err) - } - return out.String() -} diff --git a/core/asm/compiler.go b/core/asm/compiler.go deleted file mode 100644 index 02c589b2c1..0000000000 --- a/core/asm/compiler.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2017 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 . - -package asm - -import ( - "encoding/hex" - "errors" - "fmt" - "math/big" - "os" - "strings" - - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/vm" -) - -// Compiler contains information about the parsed source -// and holds the tokens for the program. -type Compiler struct { - tokens []token - out []byte - - labels map[string]int - - pc, pos int - - debug bool -} - -// NewCompiler returns a new allocated compiler. -func NewCompiler(debug bool) *Compiler { - return &Compiler{ - labels: make(map[string]int), - debug: debug, - } -} - -// Feed feeds tokens into ch and are interpreted by -// the compiler. -// -// feed is the first pass in the compile stage as it collects the used labels in the -// program and keeps a program counter which is used to determine the locations of the -// jump dests. The labels can than be used in the second stage to push labels and -// determine the right position. -func (c *Compiler) Feed(ch <-chan token) { - var prev token - for i := range ch { - switch i.typ { - case number: - num := math.MustParseBig256(i.text).Bytes() - if len(num) == 0 { - num = []byte{0} - } - c.pc += len(num) - case stringValue: - c.pc += len(i.text) - 2 - case element: - c.pc++ - case labelDef: - c.labels[i.text] = c.pc - c.pc++ - case label: - c.pc += 4 - if prev.typ == element && isJump(prev.text) { - c.pc++ - } - } - c.tokens = append(c.tokens, i) - prev = i - } - if c.debug { - fmt.Fprintln(os.Stderr, "found", len(c.labels), "labels") - } -} - -// Compile compiles the current tokens and returns a binary string that can be interpreted -// by the EVM and an error if it failed. -// -// compile is the second stage in the compile phase which compiles the tokens to EVM -// instructions. -func (c *Compiler) Compile() (string, []error) { - var errors []error - // continue looping over the tokens until - // the stack has been exhausted. - for c.pos < len(c.tokens) { - if err := c.compileLine(); err != nil { - errors = append(errors, err) - } - } - - // turn the binary to hex - h := hex.EncodeToString(c.out) - return h, errors -} - -// next returns the next token and increments the -// position. -func (c *Compiler) next() token { - token := c.tokens[c.pos] - c.pos++ - return token -} - -// compileLine compiles a single line instruction e.g. -// "push 1", "jump @label". -func (c *Compiler) compileLine() error { - n := c.next() - if n.typ != lineStart { - return compileErr(n, n.typ.String(), lineStart.String()) - } - - lvalue := c.next() - switch lvalue.typ { - case eof: - return nil - case element: - if err := c.compileElement(lvalue); err != nil { - return err - } - case labelDef: - c.compileLabel() - case lineEnd: - return nil - default: - return compileErr(lvalue, lvalue.text, fmt.Sprintf("%v or %v", labelDef, element)) - } - - if n := c.next(); n.typ != lineEnd { - return compileErr(n, n.text, lineEnd.String()) - } - - return nil -} - -// parseNumber compiles the number to bytes -func parseNumber(tok token) ([]byte, error) { - if tok.typ != number { - panic("parseNumber of non-number token") - } - num, ok := math.ParseBig256(tok.text) - if !ok { - return nil, errors.New("invalid number") - } - bytes := num.Bytes() - if len(bytes) == 0 { - bytes = []byte{0} - } - return bytes, nil -} - -// compileElement compiles the element (push & label or both) -// to a binary representation and may error if incorrect statements -// where fed. -func (c *Compiler) compileElement(element token) error { - switch { - case isJump(element.text): - return c.compileJump(element.text) - case isPush(element.text): - return c.compilePush() - default: - c.outputOpcode(toBinary(element.text)) - return nil - } -} - -func (c *Compiler) compileJump(jumpType string) error { - rvalue := c.next() - switch rvalue.typ { - case number: - numBytes, err := parseNumber(rvalue) - if err != nil { - return err - } - c.outputBytes(numBytes) - - case stringValue: - // strings are quoted, remove them. - str := rvalue.text[1 : len(rvalue.text)-2] - c.outputBytes([]byte(str)) - - case label: - c.outputOpcode(vm.PUSH4) - pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes() - pos = append(make([]byte, 4-len(pos)), pos...) - c.outputBytes(pos) - - case lineEnd: - // push without argument is supported, it just takes the destination from the stack. - c.pos-- - - default: - return compileErr(rvalue, rvalue.text, "number, string or label") - } - // push the operation - c.outputOpcode(toBinary(jumpType)) - return nil -} - -func (c *Compiler) compilePush() error { - // handle pushes. pushes are read from left to right. - var value []byte - rvalue := c.next() - switch rvalue.typ { - case number: - value = math.MustParseBig256(rvalue.text).Bytes() - if len(value) == 0 { - value = []byte{0} - } - case stringValue: - value = []byte(rvalue.text[1 : len(rvalue.text)-1]) - case label: - value = big.NewInt(int64(c.labels[rvalue.text])).Bytes() - value = append(make([]byte, 4-len(value)), value...) - default: - return compileErr(rvalue, rvalue.text, "number, string or label") - } - if len(value) > 32 { - return fmt.Errorf("%d: string or number size > 32 bytes", rvalue.lineno+1) - } - c.outputOpcode(vm.OpCode(int(vm.PUSH1) - 1 + len(value))) - c.outputBytes(value) - return nil -} - -// compileLabel pushes a jumpdest to the binary slice. -func (c *Compiler) compileLabel() { - c.outputOpcode(vm.JUMPDEST) -} - -func (c *Compiler) outputOpcode(op vm.OpCode) { - if c.debug { - fmt.Printf("%d: %v\n", len(c.out), op) - } - c.out = append(c.out, byte(op)) -} - -// output pushes the value v to the binary stack. -func (c *Compiler) outputBytes(b []byte) { - if c.debug { - fmt.Printf("%d: %x\n", len(c.out), b) - } - c.out = append(c.out, b...) -} - -// isPush returns whether the string op is either any of -// push(N). -func isPush(op string) bool { - return strings.EqualFold(op, "PUSH") -} - -// isJump returns whether the string op is jump(i) -func isJump(op string) bool { - return strings.EqualFold(op, "JUMPI") || strings.EqualFold(op, "JUMP") -} - -// toBinary converts text to a vm.OpCode -func toBinary(text string) vm.OpCode { - return vm.StringToOp(strings.ToUpper(text)) -} - -type compileError struct { - got string - want string - - lineno int -} - -func (err compileError) Error() string { - return fmt.Sprintf("%d: syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want) -} - -func compileErr(c token, got, want string) error { - return compileError{ - got: got, - want: want, - lineno: c.lineno + 1, - } -} diff --git a/core/asm/compiler_test.go b/core/asm/compiler_test.go deleted file mode 100644 index 3d64c96bc8..0000000000 --- a/core/asm/compiler_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2019 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 . - -package asm - -import ( - "testing" -) - -func TestCompiler(t *testing.T) { - tests := []struct { - input, output string - }{ - { - input: ` - GAS - label: - PUSH @label -`, - output: "5a5b6300000001", - }, - { - input: ` - PUSH @label - label: -`, - output: "63000000055b", - }, - { - input: ` - PUSH @label - JUMP - label: -`, - output: "6300000006565b", - }, - { - input: ` - JUMP @label - label: -`, - output: "6300000006565b", - }, - { - input: ` - JUMP @label -label: ;; comment - ADD ;; comment -`, - output: "6300000006565b01", - }, - } - for _, test := range tests { - ch := Lex([]byte(test.input), false) - c := NewCompiler(false) - c.Feed(ch) - output, err := c.Compile() - if len(err) != 0 { - t.Errorf("compile error: %v\ninput: %s", err, test.input) - continue - } - if output != test.output { - t.Errorf("incorrect output\ninput: %sgot: %s\nwant: %s\n", test.input, output, test.output) - } - } -} diff --git a/core/asm/lex_test.go b/core/asm/lex_test.go deleted file mode 100644 index 1e62d776d4..0000000000 --- a/core/asm/lex_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 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 . - -package asm - -import ( - "reflect" - "testing" -) - -func lexAll(src string) []token { - ch := Lex([]byte(src), false) - - var tokens []token - for i := range ch { - tokens = append(tokens, i) - } - return tokens -} - -func TestLexer(t *testing.T) { - tests := []struct { - input string - tokens []token - }{ - { - input: ";; this is a comment", - tokens: []token{{typ: lineStart}, {typ: eof}}, - }, - { - input: "0x12345678", - tokens: []token{{typ: lineStart}, {typ: number, text: "0x12345678"}, {typ: eof}}, - }, - { - input: "0x123ggg", - tokens: []token{{typ: lineStart}, {typ: number, text: "0x123"}, {typ: element, text: "ggg"}, {typ: eof}}, - }, - { - input: "12345678", - tokens: []token{{typ: lineStart}, {typ: number, text: "12345678"}, {typ: eof}}, - }, - { - input: "123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "0123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "0123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "00123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "00123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "@foo", - tokens: []token{{typ: lineStart}, {typ: label, text: "foo"}, {typ: eof}}, - }, - { - input: "@label123", - tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, - }, - // Comment after label - { - input: "@label123 ;; comment", - tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, - }, - // Comment after instruction - { - input: "push 3 ;; comment\nadd", - tokens: []token{{typ: lineStart}, {typ: element, text: "push"}, {typ: number, text: "3"}, {typ: lineEnd, text: "\n"}, {typ: lineStart, lineno: 1}, {typ: element, lineno: 1, text: "add"}, {typ: eof, lineno: 1}}, - }, - } - - for _, test := range tests { - tokens := lexAll(test.input) - if !reflect.DeepEqual(tokens, test.tokens) { - t.Errorf("input %q\ngot: %+v\nwant: %+v", test.input, tokens, test.tokens) - } - } -} diff --git a/core/asm/lexer.go b/core/asm/lexer.go deleted file mode 100644 index 630360b106..0000000000 --- a/core/asm/lexer.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2017 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 . - -package asm - -import ( - "fmt" - "os" - "strings" - "unicode" - "unicode/utf8" -) - -// stateFn is used through the lifetime of the -// lexer to parse the different values at the -// current state. -type stateFn func(*lexer) stateFn - -// token is emitted when the lexer has discovered -// a new parsable token. These are delivered over -// the tokens channels of the lexer -type token struct { - typ tokenType - lineno int - text string -} - -// tokenType are the different types the lexer -// is able to parse and return. -type tokenType int - -//go:generate go run golang.org/x/tools/cmd/stringer -type tokenType - -const ( - eof tokenType = iota // end of file - lineStart // emitted when a line starts - lineEnd // emitted when a line ends - invalidStatement // any invalid statement - element // any element during element parsing - label // label is emitted when a label is found - labelDef // label definition is emitted when a new label is found - number // number is emitted when a number is found - stringValue // stringValue is emitted when a string has been found -) - -const ( - decimalNumbers = "1234567890" // characters representing any decimal number - hexNumbers = decimalNumbers + "aAbBcCdDeEfF" // characters representing any hexadecimal - alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric -) - -// lexer is the basic construct for parsing -// source code and turning them in to tokens. -// Tokens are interpreted by the compiler. -type lexer struct { - input string // input contains the source code of the program - - tokens chan token // tokens is used to deliver tokens to the listener - state stateFn // the current state function - - lineno int // current line number in the source file - start, pos, width int // positions for lexing and returning value - - debug bool // flag for triggering debug output -} - -// Lex lexes the program by name with the given source. It returns a -// channel on which the tokens are delivered. -func Lex(source []byte, debug bool) <-chan token { - ch := make(chan token) - l := &lexer{ - input: string(source), - tokens: ch, - state: lexLine, - debug: debug, - } - go func() { - l.emit(lineStart) - for l.state != nil { - l.state = l.state(l) - } - l.emit(eof) - close(l.tokens) - }() - - return ch -} - -// next returns the next rune in the program's source. -func (l *lexer) next() (rune rune) { - if l.pos >= len(l.input) { - l.width = 0 - return 0 - } - rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) - l.pos += l.width - return rune -} - -// backup backsup the last parsed element (multi-character) -func (l *lexer) backup() { - l.pos -= l.width -} - -// peek returns the next rune but does not advance the seeker -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// ignore advances the seeker and ignores the value -func (l *lexer) ignore() { - l.start = l.pos -} - -// accept checks whether the given input matches the next rune -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - - l.backup() - - return false -} - -// acceptRun will continue to advance the seeker until valid -// can no longer be met. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// acceptRunUntil is the inverse of acceptRun and will continue -// to advance the seeker until the rune has been found. -func (l *lexer) acceptRunUntil(until rune) bool { - // Continues running until a rune is found - for i := l.next(); !strings.ContainsRune(string(until), i); i = l.next() { - if i == 0 { - return false - } - } - - return true -} - -// blob returns the current value -func (l *lexer) blob() string { - return l.input[l.start:l.pos] -} - -// Emits a new token on to token channel for processing -func (l *lexer) emit(t tokenType) { - token := token{t, l.lineno, l.blob()} - - if l.debug { - fmt.Fprintf(os.Stderr, "%04d: (%-20v) %s\n", token.lineno, token.typ, token.text) - } - - l.tokens <- token - l.start = l.pos -} - -// lexLine is state function for lexing lines -func lexLine(l *lexer) stateFn { - for { - switch r := l.next(); { - case r == '\n': - l.emit(lineEnd) - l.ignore() - l.lineno++ - l.emit(lineStart) - case r == ';' && l.peek() == ';': - return lexComment - case isSpace(r): - l.ignore() - case isLetter(r) || r == '_': - return lexElement - case isNumber(r): - return lexNumber - case r == '@': - l.ignore() - return lexLabel - case r == '"': - return lexInsideString - default: - return nil - } - } -} - -// lexComment parses the current position until the end -// of the line and discards the text. -func lexComment(l *lexer) stateFn { - l.acceptRunUntil('\n') - l.backup() - l.ignore() - - return lexLine -} - -// lexLabel parses the current label, emits and returns -// the lex text state function to advance the parsing -// process. -func lexLabel(l *lexer) stateFn { - l.acceptRun(alpha + "_" + decimalNumbers) - - l.emit(label) - - return lexLine -} - -// lexInsideString lexes the inside of a string until -// the state function finds the closing quote. -// It returns the lex text state function. -func lexInsideString(l *lexer) stateFn { - if l.acceptRunUntil('"') { - l.emit(stringValue) - } - - return lexLine -} - -func lexNumber(l *lexer) stateFn { - acceptance := decimalNumbers - if l.accept("xX") { - acceptance = hexNumbers - } - l.acceptRun(acceptance) - - l.emit(number) - - return lexLine -} - -func lexElement(l *lexer) stateFn { - l.acceptRun(alpha + "_" + decimalNumbers) - - if l.peek() == ':' { - l.emit(labelDef) - - l.accept(":") - l.ignore() - } else { - l.emit(element) - } - return lexLine -} - -func isLetter(t rune) bool { - return unicode.IsLetter(t) -} - -func isSpace(t rune) bool { - return unicode.IsSpace(t) -} - -func isNumber(t rune) bool { - return unicode.IsNumber(t) -} diff --git a/core/asm/tokentype_string.go b/core/asm/tokentype_string.go deleted file mode 100644 index ade76aa360..0000000000 --- a/core/asm/tokentype_string.go +++ /dev/null @@ -1,31 +0,0 @@ -// Code generated by "stringer -type tokenType"; DO NOT EDIT. - -package asm - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[eof-0] - _ = x[lineStart-1] - _ = x[lineEnd-2] - _ = x[invalidStatement-3] - _ = x[element-4] - _ = x[label-5] - _ = x[labelDef-6] - _ = x[number-7] - _ = x[stringValue-8] -} - -const _tokenType_name = "eoflineStartlineEndinvalidStatementelementlabellabelDefnumberstringValue" - -var _tokenType_index = [...]uint8{0, 3, 12, 19, 35, 42, 47, 55, 61, 72} - -func (i tokenType) String() string { - if i < 0 || i >= tokenType(len(_tokenType_index)-1) { - return "tokenType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _tokenType_name[_tokenType_index[i]:_tokenType_index[i+1]] -} diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index bde230b6da..d75a5b0459 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -29,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/asm" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" @@ -508,21 +507,9 @@ func TestEip2929Cases(t *testing.T) { t.Skip("Test only useful for generating documentation") id := 1 prettyPrint := func(comment string, code []byte) { - instrs := make([]string, 0) - it := asm.NewInstructionIterator(code) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - instrs = append(instrs, fmt.Sprintf("%v %#x", it.Op(), it.Arg())) - } else { - instrs = append(instrs, fmt.Sprintf("%v", it.Op())) - } - } - ops := strings.Join(instrs, ", ") fmt.Printf("### Case %d\n\n", id) id++ - fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\nOperations: \n```\n%v\n```\n\n", - comment, - code, ops) + fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\n", comment, code) Execute(code, nil, &Config{ EVMConfig: vm.Config{ Tracer: logger.NewMarkdownLogger(nil, os.Stdout).Hooks(), From 67cd4cd5a15990873d60200bffd85a8bf9abba8b Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Thu, 20 Feb 2025 10:27:13 +0100 Subject: [PATCH 29/47] .github: downgrade go for lint step (#31217) --- .github/workflows/go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 90449ef30d..4da92f2431 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.24.0 + go-version: 1.23.0 cache: false - name: Run linters From c8781be76277e5ef8c8d6933aeb21ea6f34013bd Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 20 Feb 2025 13:11:48 +0100 Subject: [PATCH 30/47] core/txpool/legacypool: add setCodeTx reorg test (#31206) This PR adds a test that makes sure that a node can send multiple transactions again once a authorization is removed --- core/txpool/legacypool/legacypool_test.go | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index da28e8a75b..7e35e0cc60 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -149,6 +149,10 @@ func pricedSetCodeTx(nonce uint64, gaslimit uint64, gasFee, tip *uint256.Int, ke }) authList = append(authList, auth) } + return pricedSetCodeTxWithAuth(nonce, gaslimit, gasFee, tip, key, authList) +} + +func pricedSetCodeTxWithAuth(nonce uint64, gaslimit uint64, gasFee, tip *uint256.Int, key *ecdsa.PrivateKey, authList []types.SetCodeAuthorization) *types.Transaction { return types.MustSignNewTx(key, types.LatestSignerForChainID(params.TestChainConfig.ChainID), &types.SetCodeTx{ ChainID: uint256.MustFromBig(params.TestChainConfig.ChainID), Nonce: nonce, @@ -2393,6 +2397,65 @@ func TestSetCodeTransactions(t *testing.T) { } } +func TestSetCodeTransactionsReorg(t *testing.T) { + t.Parallel() + + // Create the pool to test the status retrievals with + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + blockchain := newTestBlockChain(params.MergedTestChainConfig, 1000000, statedb, new(event.Feed)) + + pool := New(testTxPoolConfig, blockchain) + pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) + defer pool.Close() + + // Create the test accounts + var ( + keyA, _ = crypto.GenerateKey() + addrA = crypto.PubkeyToAddress(keyA.PublicKey) + ) + testAddBalance(pool, addrA, big.NewInt(params.Ether)) + // Send an authorization for 0x42 + var authList []types.SetCodeAuthorization + auth, _ := types.SignSetCode(keyA, types.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(params.TestChainConfig.ChainID), + Address: common.Address{0x42}, + Nonce: 0, + }) + authList = append(authList, auth) + if err := pool.addRemoteSync(pricedSetCodeTxWithAuth(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, authList)); err != nil { + t.Fatalf("failed to add with remote setcode transaction: %v", err) + } + // Simulate the chain moving + blockchain.statedb.SetNonce(addrA, 1, tracing.NonceChangeAuthorization) + blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address)) + <-pool.requestReset(nil, nil) + // Set an authorization for 0x00 + auth, _ = types.SignSetCode(keyA, types.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(params.TestChainConfig.ChainID), + Address: common.Address{}, + Nonce: 0, + }) + authList = append(authList, auth) + if err := pool.addRemoteSync(pricedSetCodeTxWithAuth(1, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, authList)); err != nil { + t.Fatalf("failed to add with remote setcode transaction: %v", err) + } + // Try to add a transactions in + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { + t.Fatalf("unexpected error %v, expecting %v", err, txpool.ErrAccountLimitExceeded) + } + // Simulate the chain moving + blockchain.statedb.SetNonce(addrA, 2, tracing.NonceChangeAuthorization) + blockchain.statedb.SetCode(addrA, nil) + <-pool.requestReset(nil, nil) + // Now send two transactions from addrA + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); err != nil { + t.Fatalf("failed to added single transaction: %v", err) + } + if err := pool.addRemoteSync(pricedTransaction(3, 100000, big.NewInt(1000), keyA)); err != nil { + t.Fatalf("failed to added single transaction: %v", err) + } +} + // Benchmarks the speed of validating the contents of the pending queue of the // transaction pool. func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } From b1f88ef9bd5d5eed77df05486ebf9c3e7c99a299 Mon Sep 17 00:00:00 2001 From: nethoxa <135072738+nethoxa@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:30:55 +0100 Subject: [PATCH 31/47] internal/ethapi: handle prague system calls in eth_simulate (#31176) eth_simulate was not processing prague system calls for history contract and EL requests resulting in inaccurate stateRoot and requestsRoot fields in the block. --- internal/ethapi/simulate.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index c461b1f0a1..227fd0e8e5 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -194,6 +194,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, if precompiles != nil { evm.SetPrecompiles(precompiles) } + if sim.chainConfig.IsPrague(header.Number, header.Time) || sim.chainConfig.IsVerkle(header.Number, header.Time) { + core.ProcessParentBlockHash(header.ParentHash, evm) + } + var allLogs []*types.Log for i, call := range block.Calls { if err := ctx.Err(); err != nil { return nil, nil, err @@ -234,9 +238,23 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, } } else { callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful) + allLogs = append(allLogs, callRes.Logs...) } callResults[i] = callRes } + var requests [][]byte + // Process EIP-7685 requests + if sim.chainConfig.IsPrague(header.Number, header.Time) { + requests = [][]byte{} + // EIP-6110 + if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil { + return nil, nil, err + } + // EIP-7002 + core.ProcessWithdrawalQueue(&requests, evm) + // EIP-7251 + core.ProcessConsolidationQueue(&requests, evm) + } header.Root = sim.state.IntermediateRoot(true) header.GasUsed = gasUsed if sim.chainConfig.IsCancun(header.Number, header.Time) { @@ -246,6 +264,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, if sim.chainConfig.IsShanghai(header.Number, header.Time) { withdrawals = make([]*types.Withdrawal, 0) } + if requests != nil { + reqHash := types.CalcRequestsHash(requests) + header.RequestsHash = &reqHash + } b := types.NewBlock(header, &types.Body{Transactions: txes, Withdrawals: withdrawals}, receipts, trie.NewStackTrie(nil)) repairLogs(callResults, b.Hash()) return b, callResults, nil From dcc0b3704d5f01a6e721c4f37ba068d3b41c64ec Mon Sep 17 00:00:00 2001 From: Delweng Date: Thu, 20 Feb 2025 22:04:35 +0800 Subject: [PATCH 32/47] eth/tracers: refactor block context in test runner (#29450) This commit contains a minor refactoring of the block context used within the test runners. --------- Signed-off-by: jsvisa --- .../internal/tracetest/calltrace_test.go | 7 ++----- .../internal/tracetest/flat_calltrace_test.go | 7 ++----- eth/tracers/internal/tracetest/makeTest.js | 17 ++++++++++----- .../internal/tracetest/prestate_test.go | 21 ++++++++----------- .../testdata/call_tracer/blob_tx.json | 2 -- .../testdata/prestate_tracer/blob_tx.json | 2 -- .../prestate_tracer/create_create.json | 2 -- eth/tracers/internal/tracetest/util.go | 14 +++++++++++-- 8 files changed, 37 insertions(+), 35 deletions(-) diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 999ab211c0..b2486661e4 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -65,11 +65,8 @@ type callTrace struct { // callTracerTest defines a single test to check the call tracer against. type callTracerTest struct { - Genesis *core.Genesis `json:"genesis"` - Context *callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result *callTrace `json:"result"` + tracerTestEnv + Result *callTrace `json:"result"` } // Iterates over all the input-output datasets in the tracer test harness and diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index 4390a62b4b..d1fa44e9d8 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -77,11 +77,8 @@ type flatCallTraceResult struct { // flatCallTracerTest defines a single test to check the call tracer against. type flatCallTracerTest struct { - Genesis *core.Genesis `json:"genesis"` - Context *callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result []flatCallTrace `json:"result"` + tracerTestEnv + Result []flatCallTrace `json:"result"` } func flatCallTracerTestRunner(tracerName string, filename string, dirPath string, t testing.TB) error { diff --git a/eth/tracers/internal/tracetest/makeTest.js b/eth/tracers/internal/tracetest/makeTest.js index 826c91f639..cb41ebde0c 100644 --- a/eth/tracers/internal/tracetest/makeTest.js +++ b/eth/tracers/internal/tracetest/makeTest.js @@ -31,6 +31,9 @@ var makeTest = function(tx, traceConfig) { delete genesis.transactions; delete genesis.transactionsRoot; delete genesis.uncles; + delete genesis.withdrawals; + delete genesis.withdrawalsRoot; + delete genesis.baseFeePerGas; genesis.gasLimit = genesis.gasLimit.toString(); genesis.number = genesis.number.toString(); @@ -60,11 +63,15 @@ var makeTest = function(tx, traceConfig) { context.baseFeePerGas = block.baseFeePerGas.toString(); } - console.log(JSON.stringify({ + var data = { genesis: genesis, context: context, - input: eth.getRawTransaction(tx), - result: result, - tracerConfig: traceConfig.tracerConfig, - }, null, 2)); + input: eth.getRawTransaction(tx), + result: result, + }; + if (traceConfig && traceConfig.tracerConfig) { + data.tracerConfig = traceConfig.tracerConfig; + } + + console.log(JSON.stringify(data, null, 2)); } diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 680645970a..29c2834ba2 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -43,28 +43,25 @@ type account struct { Storage map[common.Hash]common.Hash `json:"storage"` } -// testcase defines a single test to check the stateDiff tracer against. -type testcase struct { - Genesis *core.Genesis `json:"genesis"` - Context *callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result interface{} `json:"result"` +// prestateTracerTest defines a single test to check the stateDiff tracer against. +type prestateTracerTest struct { + tracerTestEnv + Result interface{} `json:"result"` } func TestPrestateTracerLegacy(t *testing.T) { - testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", t) + testPrestateTracer("prestateTracerLegacy", "prestate_tracer_legacy", t) } func TestPrestateTracer(t *testing.T) { - testPrestateDiffTracer("prestateTracer", "prestate_tracer", t) + testPrestateTracer("prestateTracer", "prestate_tracer", t) } func TestPrestateWithDiffModeTracer(t *testing.T) { - testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", t) + testPrestateTracer("prestateTracer", "prestate_tracer_with_diff_mode", t) } -func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { +func testPrestateTracer(tracerName string, dirPath string, t *testing.T) { files, err := os.ReadDir(filepath.Join("testdata", dirPath)) if err != nil { t.Fatalf("failed to retrieve tracer test suite: %v", err) @@ -77,7 +74,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { t.Parallel() var ( - test = new(testcase) + test = new(prestateTracerTest) tx = new(types.Transaction) ) // Call tracer test found, read if from disk diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json b/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json index f8e08532a4..f59285cfba 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json @@ -14,8 +14,6 @@ "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "stateRoot": "0x577f42ab21ccfd946511c57869ace0bdf7c217c36f02b7cd3459df0ed1cffc1a", "timestamp": "1709626771", - "withdrawals": [], - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "alloc": { "0x0000000000000000000000000000000000000000": { "balance": "0x272e0528" diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json index 9f452ca5bd..50f3209735 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json @@ -14,8 +14,6 @@ "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "stateRoot": "0x577f42ab21ccfd946511c57869ace0bdf7c217c36f02b7cd3459df0ed1cffc1a", "timestamp": "1709626771", - "withdrawals": [], - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "alloc": { "0x0000000000000000000000000000000000000000": { "balance": "0x272e0528" diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json index 489a1ae6b5..dd4fca1ecc 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json @@ -11,8 +11,6 @@ "number": "1", "stateRoot": "0xd2ebe0a7f3572ffe3e5b4c78147376d3fca767f236e4dd23f9151acfec7cb0d1", "timestamp": "1699617692", - "withdrawals": [], - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "alloc": { "0x0000000000000000000000000000000000000000": { "balance": "0x5208" diff --git a/eth/tracers/internal/tracetest/util.go b/eth/tracers/internal/tracetest/util.go index 85727e29ed..04fff12fe5 100644 --- a/eth/tracers/internal/tracetest/util.go +++ b/eth/tracers/internal/tracetest/util.go @@ -17,6 +17,7 @@ package tracetest import ( + "encoding/json" "math/big" "strings" "unicode" @@ -42,7 +43,8 @@ func camel(str string) string { return strings.Join(pieces, "") } -type callContext struct { +// traceContext defines a context used to construct the block context +type traceContext struct { Number math.HexOrDecimal64 `json:"number"` Difficulty *math.HexOrDecimal256 `json:"difficulty"` Time math.HexOrDecimal64 `json:"timestamp"` @@ -51,7 +53,7 @@ type callContext struct { BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` } -func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext { +func (c *traceContext) toBlockContext(genesis *core.Genesis) vm.BlockContext { context := vm.BlockContext{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, @@ -77,3 +79,11 @@ func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext { } return context } + +// tracerTestEnv defines a tracer test required fields +type tracerTestEnv struct { + Genesis *core.Genesis `json:"genesis"` + Context *traceContext `json:"context"` + Input string `json:"input"` + TracerConfig json.RawMessage `json:"tracerConfig"` +} From 301a868d28bd0a177f06ce9e74f673894bd7101e Mon Sep 17 00:00:00 2001 From: Martin HS Date: Thu, 20 Feb 2025 18:46:25 +0100 Subject: [PATCH 33/47] oss-fuzz: remove deprecated targets (#31224) Fixes https://github.com/ethereum/go-ethereum/issues/31223 (sorry, I thought the fork fork would be created on my repo, not upstream, when I used the GH editor) --- oss-fuzz.sh | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/oss-fuzz.sh b/oss-fuzz.sh index 1f222c433b..4db245a781 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -160,14 +160,6 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ FuzzG1Add fuzz_g1_add\ $repo/tests/fuzzers/bls12381/bls12381_test.go -compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ - FuzzCrossG1Mul fuzz_cross_g1_mul\ - $repo/tests/fuzzers/bls12381/bls12381_test.go - -compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ - FuzzG1Mul fuzz_g1_mul\ - $repo/tests/fuzzers/bls12381/bls12381_test.go - compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ FuzzG1MultiExp fuzz_g1_multiexp \ $repo/tests/fuzzers/bls12381/bls12381_test.go @@ -176,14 +168,6 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ FuzzG2Add fuzz_g2_add \ $repo/tests/fuzzers/bls12381/bls12381_test.go -compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ - FuzzCrossG2Mul fuzz_cross_g2_mul\ - $repo/tests/fuzzers/bls12381/bls12381_test.go - -compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ - FuzzG2Mul fuzz_g2_mul\ - $repo/tests/fuzzers/bls12381/bls12381_test.go - compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \ FuzzG2MultiExp fuzz_g2_multiexp \ $repo/tests/fuzzers/bls12381/bls12381_test.go From 2a81bbaa4f0988f947dfb1400c3cf707b9605ead Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 21 Feb 2025 03:42:54 +0100 Subject: [PATCH 34/47] p2p/nat: remove test with default servers (#31225) The test occasionally fails when network connectivity is bad or if it hits the wrong server. We usually don't add tests with external network dependency so I'm removing them. Fixes #31220 --- p2p/nat/stun_test.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/p2p/nat/stun_test.go b/p2p/nat/stun_test.go index b5f429986c..6bcaf45f9f 100644 --- a/p2p/nat/stun_test.go +++ b/p2p/nat/stun_test.go @@ -18,17 +18,8 @@ package nat import ( "testing" - - "github.com/stretchr/testify/assert" ) -func TestNatStun(t *testing.T) { - nat, err := newSTUN("") - assert.NoError(t, err) - _, err = nat.ExternalIP() - assert.NoError(t, err) -} - func TestUnreachedNatServer(t *testing.T) { stun := &stun{ serverList: []string{"198.51.100.2:1234", "198.51.100.5"}, From 53e8e1fdf2d41a93cd3355ccdad472cfea27289e Mon Sep 17 00:00:00 2001 From: rrhlrmrr <39875249+rrhlrmrr@users.noreply.github.com> Date: Fri, 21 Feb 2025 14:45:29 +0900 Subject: [PATCH 35/47] core/types: remove unneeded todo marker (#31179) --- core/types/transaction_marshalling.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go index 1bbb97a3ec..f76d4b92e9 100644 --- a/core/types/transaction_marshalling.go +++ b/core/types/transaction_marshalling.go @@ -514,6 +514,5 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { // Now set the inner transaction. tx.setDecoded(inner, 0) - // TODO: check hash here? return nil } From 5552ada4861717af05a9d1925983b6e04552d5cd Mon Sep 17 00:00:00 2001 From: jwasinger Date: Fri, 21 Feb 2025 00:48:24 -0800 Subject: [PATCH 36/47] signer/core: fix encoding of `bytes` nested within array (#31049) Fixes an incorrect encoding of recursive bytes types. closes https://github.com/ethereum/go-ethereum/issues/30979 --- signer/core/apitypes/types.go | 11 +++++++- signer/core/signed_data_test.go | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index b56931c1d1..b8b96bef92 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -501,7 +501,16 @@ func (typedData *TypedData) encodeArrayValue(encValue interface{}, encType strin for _, item := range arrayValue { if reflect.TypeOf(item).Kind() == reflect.Slice || reflect.TypeOf(item).Kind() == reflect.Array { - encodedData, err := typedData.encodeArrayValue(item, parsedType, depth+1) + var ( + encodedData hexutil.Bytes + err error + ) + if reflect.TypeOf(item).Elem().Kind() == reflect.Uint8 { + // the item type is bytes. encode the bytes array directly instead of recursing. + encodedData, err = typedData.EncodePrimitiveValue(parsedType, item, depth+1) + } else { + encodedData, err = typedData.encodeArrayValue(item, parsedType, depth+1) + } if err != nil { return nil, err } diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go index d0637010ba..b6c080736c 100644 --- a/signer/core/signed_data_test.go +++ b/signer/core/signed_data_test.go @@ -1014,3 +1014,49 @@ func TestComplexTypedDataWithLowercaseReftype(t *testing.T) { t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash) } } + +var recursiveBytesTypesStandard = apitypes.Types{ + "EIP712Domain": { + { + Name: "name", + Type: "string", + }, + { + Name: "version", + Type: "string", + }, + { + Name: "chainId", + Type: "uint256", + }, + { + Name: "verifyingContract", + Type: "address", + }, + }, + "Val": { + { + Name: "field", + Type: "bytes[][]", + }, + }, +} + +var recursiveBytesMessageStandard = map[string]interface{}{ + "field": [][][]byte{{{1}, {2}}, {{3}, {4}}}, +} + +var recursiveBytesTypedData = apitypes.TypedData{ + Types: recursiveBytesTypesStandard, + PrimaryType: "Val", + Domain: domainStandard, + Message: recursiveBytesMessageStandard, +} + +func TestEncodeDataRecursiveBytes(t *testing.T) { + typedData := recursiveBytesTypedData + _, err := typedData.EncodeData(typedData.PrimaryType, typedData.Message, 0) + if err != nil { + t.Fatalf("got err %v", err) + } +} From 8a14362bf7489fbfa22b6b261e336156f625bdbb Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Fri, 21 Feb 2025 09:52:55 +0100 Subject: [PATCH 37/47] internal/ethapi: fix prev hashes in eth_simulate (#31122) Shout-out to @Gabriel-Trintinalia for discovering this issue. The gist of it as follows: When processing a block, we should provide the parent block as well as the last 256 block hashes. Some of these parents data (specifically the hash) was incorrect because even though during the processing of the parent block we have updated the header, that header was not updating the TransactionsRoot and ReceiptsRoot fields (types.NewBlock makes a new copy of the header and changes it only on that instance). --------- Co-authored-by: lightclient --- internal/ethapi/api.go | 2 +- internal/ethapi/api_test.go | 96 +++++++++++++++++++++++++++++++++++++ internal/ethapi/simulate.go | 26 +++++++--- 3 files changed, 116 insertions(+), 8 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 92249f7829..f3975d35a0 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -775,7 +775,7 @@ func (api *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockN // // Note, this function doesn't make any changes in the state/blockchain and is // useful to execute and retrieve values. -func (api *BlockChainAPI) SimulateV1(ctx context.Context, opts simOpts, blockNrOrHash *rpc.BlockNumberOrHash) ([]map[string]interface{}, error) { +func (api *BlockChainAPI) SimulateV1(ctx context.Context, opts simOpts, blockNrOrHash *rpc.BlockNumberOrHash) ([]*simBlockResult, error) { if len(opts.BlockStateCalls) == 0 { return nil, &invalidParamsError{message: "empty input"} } else if len(opts.BlockStateCalls) > maxSimulateBlocks { diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index f00022e3de..d70cb90ec9 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -24,6 +24,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "os" "path/filepath" @@ -2309,6 +2310,101 @@ func TestSimulateV1(t *testing.T) { } } +func TestSimulateV1ChainLinkage(t *testing.T) { + var ( + acc = newTestAccount() + sender = acc.addr + contractAddr = common.Address{0xaa, 0xaa} + recipient = common.Address{0xbb, 0xbb} + gspec = &core.Genesis{ + Config: params.MergedTestChainConfig, + Alloc: types.GenesisAlloc{ + sender: {Balance: big.NewInt(params.Ether)}, + contractAddr: {Code: common.Hex2Bytes("5f35405f8114600f575f5260205ff35b5f80fd")}, + }, + } + signer = types.LatestSigner(params.MergedTestChainConfig) + ) + backend := newTestBackend(t, 1, gspec, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { + tx := types.MustSignNewTx(acc.key, signer, &types.LegacyTx{ + Nonce: uint64(i), + GasPrice: b.BaseFee(), + Gas: params.TxGas, + To: &recipient, + Value: big.NewInt(500), + }) + b.AddTx(tx) + }) + + ctx := context.Background() + stateDB, baseHeader, err := backend.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) + if err != nil { + t.Fatalf("failed to get state and header: %v", err) + } + + sim := &simulator{ + b: backend, + state: stateDB, + base: baseHeader, + chainConfig: backend.ChainConfig(), + gp: new(core.GasPool).AddGas(math.MaxUint64), + traceTransfers: false, + validate: false, + fullTx: false, + } + + var ( + call1 = TransactionArgs{ + From: &sender, + To: &recipient, + Value: (*hexutil.Big)(big.NewInt(1000)), + } + call2 = TransactionArgs{ + From: &sender, + To: &recipient, + Value: (*hexutil.Big)(big.NewInt(2000)), + } + call3a = TransactionArgs{ + From: &sender, + To: &contractAddr, + Input: uint256ToBytes(uint256.NewInt(baseHeader.Number.Uint64() + 1)), + Gas: newUint64(1000000), + } + call3b = TransactionArgs{ + From: &sender, + To: &contractAddr, + Input: uint256ToBytes(uint256.NewInt(baseHeader.Number.Uint64() + 2)), + Gas: newUint64(1000000), + } + blocks = []simBlock{ + {Calls: []TransactionArgs{call1}}, + {Calls: []TransactionArgs{call2}}, + {Calls: []TransactionArgs{call3a, call3b}}, + } + ) + + results, err := sim.execute(ctx, blocks) + if err != nil { + t.Fatalf("simulation execution failed: %v", err) + } + require.Equal(t, 3, len(results), "expected 3 simulated blocks") + + // Check linkages of simulated blocks: + // Verify that block2's parent hash equals block1's hash. + block1 := results[0].Block + block2 := results[1].Block + block3 := results[2].Block + require.Equal(t, block1.ParentHash(), baseHeader.Hash(), "parent hash of block1 should equal hash of base block") + require.Equal(t, block1.Hash(), block2.Header().ParentHash, "parent hash of block2 should equal hash of block1") + require.Equal(t, block2.Hash(), block3.Header().ParentHash, "parent hash of block3 should equal hash of block2") + + // In block3, two calls were executed to our contract. + // The first call in block3 should return the blockhash for block1 (i.e. block1.Hash()), + // whereas the second call should return the blockhash for block2 (i.e. block2.Hash()). + require.Equal(t, block1.Hash().Bytes(), []byte(results[2].Calls[0].ReturnValue), "returned blockhash for block1 does not match") + require.Equal(t, block2.Hash().Bytes(), []byte(results[2].Calls[1].ReturnValue), "returned blockhash for block2 does not match") +} + func TestSignTransaction(t *testing.T) { t.Parallel() // Initialize test accounts diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 227fd0e8e5..ac76372424 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -73,6 +73,20 @@ func (r *simCallResult) MarshalJSON() ([]byte, error) { return json.Marshal((*callResultAlias)(r)) } +// simBlockResult is the result of a simulated block. +type simBlockResult struct { + fullTx bool + chainConfig *params.ChainConfig + Block *types.Block + Calls []simCallResult +} + +func (r *simBlockResult) MarshalJSON() ([]byte, error) { + blockData := RPCMarshalBlock(r.Block, true, r.fullTx, r.chainConfig) + blockData["calls"] = r.Calls + return json.Marshal(blockData) +} + // simOpts are the inputs to eth_simulateV1. type simOpts struct { BlockStateCalls []simBlock @@ -95,7 +109,7 @@ type simulator struct { } // execute runs the simulation of a series of blocks. -func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]map[string]interface{}, error) { +func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]*simBlockResult, error) { if err := ctx.Err(); err != nil { return nil, err } @@ -123,7 +137,7 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]map[str return nil, err } var ( - results = make([]map[string]interface{}, len(blocks)) + results = make([]*simBlockResult, len(blocks)) parent = sim.base ) for bi, block := range blocks { @@ -131,11 +145,9 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]map[str if err != nil { return nil, err } - enc := RPCMarshalBlock(result, true, sim.fullTx, sim.chainConfig) - enc["calls"] = callResults - results[bi] = enc - - parent = headers[bi] + headers[bi] = result.Header() + results[bi] = &simBlockResult{fullTx: sim.fullTx, chainConfig: sim.chainConfig, Block: result, Calls: callResults} + parent = result.Header() } return results, nil } From cb9653d253be1ac2f04f10136655165bd8af2276 Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Fri, 21 Feb 2025 11:45:02 +0100 Subject: [PATCH 38/47] cmd/clef: improve documentation in readme (#31218) Fixed broken or outdated links and improved documentation formatting to ensure consistency and correct references. --------- Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- cmd/clef/intapi_changelog.md | 2 +- signer/core/testdata/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/clef/intapi_changelog.md b/cmd/clef/intapi_changelog.md index eaeb2e6862..85d04f6d0e 100644 --- a/cmd/clef/intapi_changelog.md +++ b/cmd/clef/intapi_changelog.md @@ -94,7 +94,7 @@ type Account struct { > Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params","Internal error" ### 3.1.0 -* Add `ContentType` `string` to `SignDataRequest` to accommodate the latest EIP-191 and EIP-712 implementations. +* Add `ContentType` `string` to `SignDataRequest` to accommodate the latest [EIP-191](https://eips.ethereum.org/EIPS/eip-191) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) implementations. ### 3.0.0 diff --git a/signer/core/testdata/README.md b/signer/core/testdata/README.md index f425450a06..85aa70c04c 100644 --- a/signer/core/testdata/README.md +++ b/signer/core/testdata/README.md @@ -1,5 +1,5 @@ -### EIP 712 tests +### EIP-712 tests -These tests are json files which are converted into eip-712 typed data. +These tests are json files which are converted into [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed data. All files are expected to be proper json, and tests will fail if they are not. Files that begin with `expfail' are expected to not pass the hashstruct construction. From d103f179b917b06bba38331627674170ed24c2a5 Mon Sep 17 00:00:00 2001 From: levisyin Date: Fri, 21 Feb 2025 20:36:18 +0800 Subject: [PATCH 39/47] build: replace `tenv` linter with `usetesting` (#31172) --- .golangci.yml | 2 +- README.md | 2 +- cmd/clef/run_test.go | 8 +------- cmd/utils/history_test.go | 6 +----- core/txpool/blobpool/blobpool_test.go | 19 +++++++------------ crypto/crypto_test.go | 4 ++-- crypto/signify/signify_test.go | 16 ++++------------ internal/era/era_test.go | 3 ++- node/config_test.go | 3 +-- 9 files changed, 20 insertions(+), 43 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b63251055b..a702da524b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,7 +25,7 @@ linters: - gocheckcompilerdirectives - reassign - mirror - - tenv + - usetesting ### linters we tried and will not be using: ### # - structcheck # lots of false positives diff --git a/README.md b/README.md index fb82459d34..9ccfe933aa 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ archives are published at https://geth.ethereum.org/downloads/. For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth). -Building `geth` requires both a Go (version 1.22 or later) and a C compiler. You can install +Building `geth` requires both a Go (version 1.23 or later) and a C compiler. You can install them using your favourite package manager. Once the dependencies are installed, run ```shell diff --git a/cmd/clef/run_test.go b/cmd/clef/run_test.go index 5fa6e02e14..d404457ba2 100644 --- a/cmd/clef/run_test.go +++ b/cmd/clef/run_test.go @@ -57,13 +57,7 @@ func TestMain(m *testing.M) { // This method creates a temporary keystore folder which will be removed after // the test exits. func runClef(t *testing.T, args ...string) *testproc { - ddir, err := os.MkdirTemp("", "cleftest-*") - if err != nil { - return nil - } - t.Cleanup(func() { - os.RemoveAll(ddir) - }) + ddir := t.TempDir() return runWithKeystore(t, ddir, args...) } diff --git a/cmd/utils/history_test.go b/cmd/utils/history_test.go index 07cf71234e..8654c454f9 100644 --- a/cmd/utils/history_test.go +++ b/cmd/utils/history_test.go @@ -87,11 +87,7 @@ func TestHistoryImportAndExport(t *testing.T) { } // Make temp directory for era files. - dir, err := os.MkdirTemp("", "history-export-test") - if err != nil { - t.Fatalf("error creating temp test directory: %v", err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() // Export history to temp directory. if err := ExportHistory(chain, dir, 0, count, step); err != nil { diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 8589e5c01d..d9137cb679 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -21,6 +21,7 @@ import ( "crypto/ecdsa" "crypto/sha256" "errors" + "fmt" "math" "math/big" "os" @@ -452,8 +453,7 @@ func TestOpenDrops(t *testing.T) { //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) + storage := t.TempDir() os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil) @@ -775,8 +775,7 @@ func TestOpenIndex(t *testing.T) { //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) + storage := t.TempDir() os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil) @@ -864,8 +863,7 @@ func TestOpenHeap(t *testing.T) { //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) + storage := t.TempDir() os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil) @@ -951,8 +949,7 @@ func TestOpenCap(t *testing.T) { //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) + storage := t.TempDir() os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil) @@ -1041,8 +1038,7 @@ func TestChangingSlotterSize(t *testing.T) { //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) + storage := t.TempDir() os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(6), nil) @@ -1508,8 +1504,7 @@ func TestAdd(t *testing.T) { } for i, tt := range tests { // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) // late defer, still ok + storage := filepath.Join(t.TempDir(), fmt.Sprintf("test-%d", i)) os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil) diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index da123cf980..5b0c9c0533 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -181,7 +181,7 @@ func TestLoadECDSA(t *testing.T) { } for _, test := range tests { - f, err := os.CreateTemp("", "loadecdsa_test.*.txt") + f, err := os.CreateTemp(t.TempDir(), "loadecdsa_test.*.txt") if err != nil { t.Fatal(err) } @@ -202,7 +202,7 @@ func TestLoadECDSA(t *testing.T) { } func TestSaveECDSA(t *testing.T) { - f, err := os.CreateTemp("", "saveecdsa_test.*.txt") + f, err := os.CreateTemp(t.TempDir(), "saveecdsa_test.*.txt") if err != nil { t.Fatal(err) } diff --git a/crypto/signify/signify_test.go b/crypto/signify/signify_test.go index 9bac2c825f..ce41c1bd04 100644 --- a/crypto/signify/signify_test.go +++ b/crypto/signify/signify_test.go @@ -33,11 +33,10 @@ var ( ) func TestSignify(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") + tmpFile, err := os.CreateTemp(t.TempDir(), "") if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name()) defer tmpFile.Close() data := make([]byte, 1024) @@ -52,7 +51,6 @@ func TestSignify(t *testing.T) { if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name() + ".sig") // Verify the signature using a golang library sig, err := minisign.NewSignatureFromFile(tmpFile.Name() + ".sig") @@ -75,11 +73,10 @@ func TestSignify(t *testing.T) { } func TestSignifyTrustedCommentTooManyLines(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") + tmpFile, err := os.CreateTemp(t.TempDir(), "") if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name()) defer tmpFile.Close() data := make([]byte, 1024) @@ -94,15 +91,13 @@ func TestSignifyTrustedCommentTooManyLines(t *testing.T) { if err == nil || err.Error() == "" { t.Fatalf("should have errored on a multi-line trusted comment, got %v", err) } - defer os.Remove(tmpFile.Name() + ".sig") } func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") + tmpFile, err := os.CreateTemp(t.TempDir(), "") if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name()) defer tmpFile.Close() data := make([]byte, 1024) @@ -117,15 +112,13 @@ func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) { if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name() + ".sig") } func TestSignifyTrustedCommentEmpty(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") + tmpFile, err := os.CreateTemp(t.TempDir(), "") if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name()) defer tmpFile.Close() data := make([]byte, 1024) @@ -140,5 +133,4 @@ func TestSignifyTrustedCommentEmpty(t *testing.T) { if err != nil { t.Fatal(err) } - defer os.Remove(tmpFile.Name() + ".sig") } diff --git a/internal/era/era_test.go b/internal/era/era_test.go index e0bebfa449..72c3b385dd 100644 --- a/internal/era/era_test.go +++ b/internal/era/era_test.go @@ -37,7 +37,7 @@ func TestEra1Builder(t *testing.T) { t.Parallel() // Get temp directory. - f, err := os.CreateTemp("", "era1-test") + f, err := os.CreateTemp(t.TempDir(), "era1-test") if err != nil { t.Fatalf("error creating temp file: %v", err) } @@ -78,6 +78,7 @@ func TestEra1Builder(t *testing.T) { if err != nil { t.Fatalf("failed to open era: %v", err) } + defer e.Close() it, err := NewRawIterator(e) if err != nil { t.Fatalf("failed to make iterator: %s", err) diff --git a/node/config_test.go b/node/config_test.go index e8af8ddcd8..067796d665 100644 --- a/node/config_test.go +++ b/node/config_test.go @@ -53,13 +53,12 @@ func TestDatadirCreation(t *testing.T) { t.Fatalf("freshly created datadir not accessible: %v", err) } // Verify that an impossible datadir fails creation - file, err := os.CreateTemp("", "") + file, err := os.CreateTemp(t.TempDir(), "") if err != nil { t.Fatalf("failed to create temporary file: %v", err) } defer func() { file.Close() - os.Remove(file.Name()) }() dir = filepath.Join(file.Name(), "invalid/path") From 9e6f9246713be4401ab1bae41f0632379f208aec Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sun, 23 Feb 2025 17:38:32 +0100 Subject: [PATCH 40/47] eth: report error from setupDiscovery at startup (#31233) I ran into this while trying to debug a discv5 thing. I tried to disable DNS discovery using `--discovery.dns=false`, which doesn't work. Annoyingly, geth started anyway and discarded the error silently. I eventually found my mistake, but it took way longer than it should have. Also including a small change to the error message for invalid DNS URLs here. The user actually needs to see the URL to make sense of the error. --- eth/backend.go | 4 +++- p2p/dnsdisc/client.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index fea7e4e1fe..f3a8bf3078 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -368,7 +368,9 @@ func (s *Ethereum) Protocols() []p2p.Protocol { // Start implements node.Lifecycle, starting all internal goroutines needed by the // Ethereum protocol implementation. func (s *Ethereum) Start() error { - s.setupDiscovery() + if err := s.setupDiscovery(); err != nil { + return err + } // Start the bloom bits servicing goroutines s.startBloomHandlers(params.BloomBitsBlocks) diff --git a/p2p/dnsdisc/client.go b/p2p/dnsdisc/client.go index 4f14d860e1..ac369ce07d 100644 --- a/p2p/dnsdisc/client.go +++ b/p2p/dnsdisc/client.go @@ -263,7 +263,7 @@ func (it *randomIterator) Next() bool { func (it *randomIterator) addTree(url string) error { le, err := parseLink(url) if err != nil { - return fmt.Errorf("invalid enrtree URL: %v", err) + return fmt.Errorf("invalid DNS discovery URL %q: %v", url, err) } it.lc.addLink("", le.str) return nil From a0e6381c48e95e42b70f7ac7018f690596de3fc6 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 24 Feb 2025 10:31:33 +0100 Subject: [PATCH 41/47] go.mod: update cloudflare-go (#31240) Updates cloudflare-go from v0.79.0 to v0.114.0 which also gets rid of a dependency to `github.com/hashicorp/go-retryablehttp` which had a security flaw. Diff: https://github.com/cloudflare/cloudflare-go/compare/v0.79.0...v0.114.0 I did a quick sanity check on the diff on all methods that we use and went through the release notes, there was nothing related to how we use it afaict --- go.mod | 16 +++++++--------- go.sum | 35 ++++++++++++++--------------------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index c9f4a4e4ba..f86973e0f6 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.13.43 github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 github.com/cespare/cp v0.1.0 - github.com/cloudflare/cloudflare-go v0.79.0 + github.com/cloudflare/cloudflare-go v0.114.0 github.com/cockroachdb/pebble v1.1.2 github.com/consensys/gnark-crypto v0.14.0 github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a @@ -58,17 +58,17 @@ require ( github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.2.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/supranational/blst v0.3.14 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.27.5 go.uber.org/automaxprocs v1.5.2 golang.org/x/crypto v0.32.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.10.0 golang.org/x/sys v0.29.0 golang.org/x/text v0.21.0 - golang.org/x/time v0.5.0 + golang.org/x/time v0.9.0 golang.org/x/tools v0.29.0 google.golang.org/protobuf v1.34.2 gopkg.in/natefinch/lumberjack.v2 v2.2.1 @@ -98,20 +98,18 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.22 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/deepmap/oapi-codegen v1.6.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-json v0.10.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect @@ -142,7 +140,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.34.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 9812cbbab5..753ddbc9a5 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,8 @@ github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86c github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M= -github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= +github.com/cloudflare/cloudflare-go v0.114.0 h1:ucoti4/7Exo0XQ+rzpn1H+IfVVe++zgiM+tyKtf0HUA= +github.com/cloudflare/cloudflare-go v0.114.0/go.mod h1:O7fYfFfA6wKqKFn2QIR9lhj7FDw6VQCGOY6hd2TBtd0= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -128,8 +128,8 @@ github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= @@ -206,8 +206,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -292,13 +292,6 @@ github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY4 github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= -github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -506,8 +499,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -516,13 +509,13 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -738,8 +731,8 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From fbe00050707590f0fc4485c131a59af83f50342c Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 24 Feb 2025 12:23:25 +0100 Subject: [PATCH 42/47] crypto: add comment to FromECDSAPub (#31241) closes https://github.com/ethereum/go-ethereum/issues/26240 --- crypto/crypto.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crypto/crypto.go b/crypto/crypto.go index f9979aa4bb..13e9b134f0 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -184,6 +184,9 @@ func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) { return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil } +// FromECDSAPub converts a secp256k1 public key to bytes. +// Note: it does not use the curve from pub, instead it always +// encodes using secp256k1. func FromECDSAPub(pub *ecdsa.PublicKey) []byte { if pub == nil || pub.X == nil || pub.Y == nil { return nil From 9211a0e3ec778680916d52b6345f23bf262cfc0f Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Tue, 25 Feb 2025 05:17:21 +0800 Subject: [PATCH 43/47] core/txpool: move setcode tx validation into legacyPool (#31209) In this PR, several improvements have been made: Authorization-related validations have been moved to legacyPool. Previously, these checks were part of the standard validation procedure, which applies common validations across different pools. Since these checks are specific to SetCode transactions, relocating them to legacyPool is a more reasonable choice. Additionally, authorization conflict checks are now performed regardless of whether the transaction is a replacement or not. --------- Co-authored-by: lightclient --- core/txpool/errors.go | 13 ---- core/txpool/legacypool/legacypool.go | 84 +++++++++++++++-------- core/txpool/legacypool/legacypool_test.go | 24 +++---- core/txpool/validation.go | 19 ++--- 4 files changed, 71 insertions(+), 69 deletions(-) diff --git a/core/txpool/errors.go b/core/txpool/errors.go index 32e49db87c..c38644857e 100644 --- a/core/txpool/errors.go +++ b/core/txpool/errors.go @@ -51,22 +51,9 @@ var ( // making the transaction invalid, rather a DOS protection. ErrOversizedData = errors.New("oversized data") - // ErrFutureReplacePending is returned if a future transaction replaces a pending - // one. Future transactions should only be able to replace other future transactions. - ErrFutureReplacePending = errors.New("future transaction tries to replace pending") - // ErrAlreadyReserved is returned if the sender address has a pending transaction // in a different subpool. For example, this error is returned in response to any // input transaction of non-blob type when a blob transaction from this sender // remains pending (and vice-versa). ErrAlreadyReserved = errors.New("address already reserved") - - // ErrAuthorityReserved is returned if a transaction has an authorization - // signed by an address which already has in-flight transactions known to the - // pool. - ErrAuthorityReserved = errors.New("authority already reserved") - - // ErrAuthorityNonce is returned if a transaction has an authorization with - // a nonce that is not currently valid for the authority. - ErrAuthorityNonceTooLow = errors.New("authority nonce too low") ) diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index c7ff954a49..4250283b03 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -61,6 +61,19 @@ var ( // ErrTxPoolOverflow is returned if the transaction pool is full and can't accept // another remote transaction. ErrTxPoolOverflow = errors.New("txpool is full") + + // ErrInflightTxLimitReached is returned when the maximum number of in-flight + // transactions is reached for specific accounts. + ErrInflightTxLimitReached = errors.New("in-flight transaction limit reached for delegated accounts") + + // ErrAuthorityReserved is returned if a transaction has an authorization + // signed by an address which already has in-flight transactions known to the + // pool. + ErrAuthorityReserved = errors.New("authority already reserved") + + // ErrFutureReplacePending is returned if a future transaction replaces a pending + // one. Future transactions should only be able to replace other future transactions. + ErrFutureReplacePending = errors.New("future transaction tries to replace pending") ) var ( @@ -572,22 +585,8 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error { opts := &txpool.ValidationOptionsWithState{ State: pool.currentState, - FirstNonceGap: nil, // Pool allows arbitrary arrival order, don't invalidate nonce gaps - UsedAndLeftSlots: func(addr common.Address) (int, int) { - var have int - if list := pool.pending[addr]; list != nil { - have += list.Len() - } - if list := pool.queue[addr]; list != nil { - have += list.Len() - } - if pool.currentState.GetCodeHash(addr) != types.EmptyCodeHash || len(pool.all.auths[addr]) != 0 { - // Allow at most one in-flight tx for delegated accounts or those with - // a pending authorization. - return have, max(0, 1-have) - } - return have, math.MaxInt - }, + FirstNonceGap: nil, // Pool allows arbitrary arrival order, don't invalidate nonce gaps + UsedAndLeftSlots: nil, // Pool has own mechanism to limit the number of transactions ExistingExpenditure: func(addr common.Address) *big.Int { if list := pool.pending[addr]; list != nil { return list.totalcost.ToBig() @@ -602,22 +601,49 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error { } return nil }, - KnownConflicts: func(from common.Address, auths []common.Address) []common.Address { - var conflicts []common.Address - // Authorities cannot conflict with any pending or queued transactions. - for _, addr := range auths { - if list := pool.pending[addr]; list != nil { - conflicts = append(conflicts, addr) - } else if list := pool.queue[addr]; list != nil { - conflicts = append(conflicts, addr) - } - } - return conflicts - }, } if err := txpool.ValidateTransactionWithState(tx, pool.signer, opts); err != nil { return err } + return pool.validateAuth(tx) +} + +// validateAuth verifies that the transaction complies with code authorization +// restrictions brought by SetCode transaction type. +func (pool *LegacyPool) validateAuth(tx *types.Transaction) error { + from, _ := types.Sender(pool.signer, tx) // validated + + // Allow at most one in-flight tx for delegated accounts or those with a + // pending authorization. + if pool.currentState.GetCodeHash(from) != types.EmptyCodeHash || len(pool.all.auths[from]) != 0 { + var ( + count int + exists bool + ) + pending := pool.pending[from] + if pending != nil { + count += pending.Len() + exists = pending.Contains(tx.Nonce()) + } + queue := pool.queue[from] + if queue != nil { + count += queue.Len() + exists = exists || queue.Contains(tx.Nonce()) + } + // Replace the existing in-flight transaction for delegated accounts + // are still supported + if count >= 1 && !exists { + return ErrInflightTxLimitReached + } + } + // Authorities cannot conflict with any pending or queued transactions. + if auths := tx.SetCodeAuthorities(); len(auths) > 0 { + for _, auth := range auths { + if pool.pending[auth] != nil || pool.queue[auth] != nil { + return ErrAuthorityReserved + } + } + } return nil } @@ -709,7 +735,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { pool.priced.Put(dropTx) } log.Trace("Discarding future transaction replacing pending tx", "hash", hash) - return false, txpool.ErrFutureReplacePending + return false, ErrFutureReplacePending } } diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 7e35e0cc60..b2a068467f 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -1645,8 +1645,8 @@ func TestUnderpricing(t *testing.T) { t.Fatalf("failed to add well priced transaction: %v", err) } // Ensure that replacing a pending transaction with a future transaction fails - if err := pool.addRemoteSync(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending { - t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending) + if err := pool.addRemoteSync(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != ErrFutureReplacePending { + t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, ErrFutureReplacePending) } pending, queued = pool.Stats() if pending != 4 { @@ -2248,12 +2248,12 @@ func TestSetCodeTransactions(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyA)); err != nil { t.Fatalf("%s: failed to add remote transaction: %v", name, err) } - if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { - t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrInflightTxLimitReached) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrInflightTxLimitReached, err) } // Also check gapped transaction. - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { - t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrInflightTxLimitReached) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrInflightTxLimitReached, err) } // Replace by fee. if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keyA)); err != nil { @@ -2287,8 +2287,8 @@ func TestSetCodeTransactions(t *testing.T) { t.Fatalf("%s: failed to add with pending delegatio: %v", name, err) } // Also check gapped transaction is rejected. - if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { - t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) + if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, ErrInflightTxLimitReached) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrInflightTxLimitReached, err) } }, }, @@ -2363,7 +2363,7 @@ func TestSetCodeTransactions(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { t.Fatalf("%s: failed to added single pooled for account with pending delegation: %v", name, err) } - if err, want := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1000), keyC)), txpool.ErrAccountLimitExceeded; !errors.Is(err, want) { + if err, want := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1000), keyC)), ErrInflightTxLimitReached; !errors.Is(err, want) { t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) } }, @@ -2376,7 +2376,7 @@ func TestSetCodeTransactions(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) } - if err, want := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})), txpool.ErrAuthorityReserved; !errors.Is(err, want) { + if err, want := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})), ErrAuthorityReserved; !errors.Is(err, want) { t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) } }, @@ -2440,8 +2440,8 @@ func TestSetCodeTransactionsReorg(t *testing.T) { t.Fatalf("failed to add with remote setcode transaction: %v", err) } // Try to add a transactions in - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { - t.Fatalf("unexpected error %v, expecting %v", err, txpool.ErrAccountLimitExceeded) + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); !errors.Is(err, ErrInflightTxLimitReached) { + t.Fatalf("unexpected error %v, expecting %v", err, ErrInflightTxLimitReached) } // Simulate the chain moving blockchain.statedb.SetNonce(addrA, 2, tracing.NonceChangeAuthorization) diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 4d53c386b6..9565c77def 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -206,7 +206,7 @@ type ValidationOptionsWithState struct { // nonce gaps will be ignored and permitted. FirstNonceGap func(addr common.Address) uint64 - // UsedAndLeftSlots is a mandatory callback to retrieve the number of tx slots + // UsedAndLeftSlots is an optional callback to retrieve the number of tx slots // used and the number still permitted for an account. New transactions will // be rejected once the number of remaining slots reaches zero. UsedAndLeftSlots func(addr common.Address) (int, int) @@ -218,11 +218,6 @@ type ValidationOptionsWithState struct { // ExistingCost is a mandatory callback to retrieve an already pooled // transaction's cost with the given nonce to check for overdrafts. ExistingCost func(addr common.Address, nonce uint64) *big.Int - - // KnownConflicts is an optional callback which iterates over the list of - // addresses and returns all addresses known to the pool with in-flight - // transactions. - KnownConflicts func(sender common.Address, authorizers []common.Address) []common.Address } // ValidateTransactionWithState is a helper method to check whether a transaction @@ -273,15 +268,9 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op // Transaction takes a new nonce value out of the pool. Ensure it doesn't // overflow the number of permitted transactions from a single account // (i.e. max cancellable via out-of-bound transaction). - if used, left := opts.UsedAndLeftSlots(from); left <= 0 { - return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used) - } - - // Verify no authorizations will invalidate existing transactions known to - // the pool. - if opts.KnownConflicts != nil { - if conflicts := opts.KnownConflicts(from, tx.SetCodeAuthorities()); len(conflicts) > 0 { - return fmt.Errorf("%w: authorization conflicts with other known tx", ErrAuthorityReserved) + if opts.UsedAndLeftSlots != nil { + if used, left := opts.UsedAndLeftSlots(from); left <= 0 { + return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used) } } } From 7d8aca95d28c4e8560a657fd1ff7852ad4eee72c Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 00:42:00 +0100 Subject: [PATCH 44/47] params: add deposit contract addresses (#31247) We forgot to add the deposit contract address for holesky, causing deposits to not be flagged correctly --------- Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- params/config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/params/config.go b/params/config.go index 523c987f01..593c70b139 100644 --- a/params/config.go +++ b/params/config.go @@ -88,6 +88,7 @@ var ( ShanghaiTime: newUint64(1696000704), CancunTime: newUint64(1707305664), PragueTime: newUint64(1740434112), + DepositContractAddress: common.HexToAddress("0x4242424242424242424242424242424242424242"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, @@ -117,6 +118,7 @@ var ( ShanghaiTime: newUint64(1677557088), CancunTime: newUint64(1706655072), PragueTime: newUint64(1741159776), + DepositContractAddress: common.HexToAddress("0x7f02c3e3c98b133055b8b348b2ac625669ed295d"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, From f6883431c28abeda55690976c2a8b59343df1e5a Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 25 Feb 2025 12:21:35 +0100 Subject: [PATCH 45/47] ethclient/simulated: add goroutine leak test (#31033) Adds a basic sanity test case to catch any go-routines leaked from instantiation/closing of a simulated backend. --- ethclient/simulated/backend_test.go | 19 +++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 3 files changed, 22 insertions(+) diff --git a/ethclient/simulated/backend_test.go b/ethclient/simulated/backend_test.go index 5bf3c6be27..fc78e84362 100644 --- a/ethclient/simulated/backend_test.go +++ b/ethclient/simulated/backend_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + "go.uber.org/goleak" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/holiman/uint256" @@ -350,3 +352,20 @@ func TestAdjustTimeAfterFork(t *testing.T) { t.Errorf("failed to build block on fork") } } + +func createAndCloseSimBackend() { + genesisData := types.GenesisAlloc{} + simulatedBackend := NewBackend(genesisData) + defer simulatedBackend.Close() +} + +// TestCheckSimBackendGoroutineLeak checks whether creation of a simulated backend leaks go-routines. Any long-lived go-routines +// spawned by global variables are not considered leaked. +func TestCheckSimBackendGoroutineLeak(t *testing.T) { + createAndCloseSimBackend() + ignoreCur := goleak.IgnoreCurrent() + // ignore this leveldb function: this go-routine is guaranteed to be terminated 1 second after closing db handle + ignoreLdb := goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain") + createAndCloseSimBackend() + goleak.VerifyNone(t, ignoreCur, ignoreLdb) +} diff --git a/go.mod b/go.mod index f86973e0f6..e58d8fd828 100644 --- a/go.mod +++ b/go.mod @@ -63,6 +63,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/urfave/cli/v2 v2.27.5 go.uber.org/automaxprocs v1.5.2 + go.uber.org/goleak v1.3.0 golang.org/x/crypto v0.32.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.10.0 diff --git a/go.sum b/go.sum index 753ddbc9a5..0dbd79cfaa 100644 --- a/go.sum +++ b/go.sum @@ -528,6 +528,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= From 756310fa43b8beab12b4fbe5fb663bc79285c8d2 Mon Sep 17 00:00:00 2001 From: Shude Li Date: Tue, 25 Feb 2025 20:40:57 +0800 Subject: [PATCH 46/47] eth/protocols/eth: fix loading "eth" ENR key in dial filter (#31251) This fixes an issue where dial candidates from discv5 would be ignored because the "eth" ENR entry was not loaded correctly. --- eth/protocols/eth/discovery.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eth/protocols/eth/discovery.go b/eth/protocols/eth/discovery.go index 075a85b69c..f43e6f864d 100644 --- a/eth/protocols/eth/discovery.go +++ b/eth/protocols/eth/discovery.go @@ -42,6 +42,7 @@ func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) { var newHead = make(chan core.ChainHeadEvent, 10) sub := chain.SubscribeChainHeadEvent(newHead) + ln.Set(currentENREntry(chain)) go func() { defer sub.Unsubscribe() for { @@ -71,7 +72,7 @@ func NewNodeFilter(chain *core.BlockChain) func(*enode.Node) bool { filter := forkid.NewFilter(chain) return func(n *enode.Node) bool { var entry enrEntry - if err := n.Load(entry); err != nil { + if err := n.Load(&entry); err != nil { return false } err := filter(entry.ForkID) From 612c9e0f4ae483f180ef96ace86effec6dc9bb0e Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 25 Feb 2025 16:18:34 +0100 Subject: [PATCH 47/47] version: release go-ethereum v1.15.3 stable --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index f0fb3195b3..cf01564d71 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 3 // Patch version component of the current release - Meta = "unstable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 3 // Patch version component of the current release + Meta = "stable" // Version metadata to append to the version string )