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 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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=