mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-12 14:19:04 +00:00
Merge remote-tracking branch 'origin/master' into eof-opcodes
This commit is contained in:
commit
02a16f1802
23 changed files with 423 additions and 84 deletions
3
cmd/evm/testdata/evmrun/3.out.1.txt
vendored
3
cmd/evm/testdata/evmrun/3.out.1.txt
vendored
|
|
@ -1,12 +1,13 @@
|
|||
{
|
||||
"root": "b444481d1367188172f8c6091e948aaa68bae763fd26d6b9e994306a66bf69f9",
|
||||
"accounts": {
|
||||
"pre(0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142)": {
|
||||
"0x0000000000000000000000007265636569766572": {
|
||||
"balance": "0",
|
||||
"nonce": 0,
|
||||
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"codeHash": "0x3e48ef54b89079a075f3b8fc253c657a86b110a7aed3568c1517b10edf2c3eb6",
|
||||
"code": "0x6040",
|
||||
"address": "0x0000000000000000000000007265636569766572",
|
||||
"key": "0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
cmd/evm/testdata/evmrun/4.out.1.txt
vendored
3
cmd/evm/testdata/evmrun/4.out.1.txt
vendored
|
|
@ -1,12 +1,13 @@
|
|||
{
|
||||
"root": "b444481d1367188172f8c6091e948aaa68bae763fd26d6b9e994306a66bf69f9",
|
||||
"accounts": {
|
||||
"pre(0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142)": {
|
||||
"0x0000000000000000000000007265636569766572": {
|
||||
"balance": "0",
|
||||
"nonce": 0,
|
||||
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"codeHash": "0x3e48ef54b89079a075f3b8fc253c657a86b110a7aed3568c1517b10edf2c3eb6",
|
||||
"code": "0x6040",
|
||||
"address": "0x0000000000000000000000007265636569766572",
|
||||
"key": "0x30d7a0694cb29af31b982480e11d7ebb003a3fca4026939149071f014689b142"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<<types.LegacyTxType |
|
||||
1<<types.AccessListTxType |
|
||||
1<<types.DynamicFeeTxType,
|
||||
1<<types.DynamicFeeTxType |
|
||||
1<<types.SetCodeTxType,
|
||||
MaxSize: txMaxSize,
|
||||
MinTip: pool.gasTip.Load().ToBig(),
|
||||
}
|
||||
|
|
@ -565,6 +581,11 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
|
|||
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
|
||||
},
|
||||
ExistingExpenditure: func(addr common.Address) *big.Int {
|
||||
|
|
@ -581,6 +602,18 @@ 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
|
||||
|
|
@ -1334,15 +1367,13 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T
|
|||
// Drop all transactions that are deemed too old (low nonce)
|
||||
forwards := list.Forward(pool.currentState.GetNonce(addr))
|
||||
for _, tx := range forwards {
|
||||
hash := tx.Hash()
|
||||
pool.all.Remove(hash)
|
||||
pool.all.Remove(tx.Hash())
|
||||
}
|
||||
log.Trace("Removed old queued transactions", "count", len(forwards))
|
||||
// Drop all transactions that are too costly (low balance or out of gas)
|
||||
drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
|
||||
for _, tx := range drops {
|
||||
hash := tx.Hash()
|
||||
pool.all.Remove(hash)
|
||||
pool.all.Remove(tx.Hash())
|
||||
}
|
||||
log.Trace("Removed unpayable queued transactions", "count", len(drops))
|
||||
queuedNofundsMeter.Mark(int64(len(drops)))
|
||||
|
|
@ -1531,8 +1562,8 @@ func (pool *LegacyPool) demoteUnexecutables() {
|
|||
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
|
||||
for _, tx := range drops {
|
||||
hash := tx.Hash()
|
||||
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
||||
pool.all.Remove(hash)
|
||||
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
||||
}
|
||||
pendingNofundsMeter.Mark(int64(len(drops)))
|
||||
|
||||
|
|
@ -1641,12 +1672,15 @@ type lookup struct {
|
|||
slots int
|
||||
lock sync.RWMutex
|
||||
txs map[common.Hash]*types.Transaction
|
||||
|
||||
auths map[common.Address][]common.Hash // All accounts with a pooled authorization
|
||||
}
|
||||
|
||||
// newLookup returns a new lookup structure.
|
||||
func newLookup() *lookup {
|
||||
return &lookup{
|
||||
txs: make(map[common.Hash]*types.Transaction),
|
||||
txs: make(map[common.Hash]*types.Transaction),
|
||||
auths: make(map[common.Address][]common.Hash),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1697,6 +1731,7 @@ func (t *lookup) Add(tx *types.Transaction) {
|
|||
slotsGauge.Update(int64(t.slots))
|
||||
|
||||
t.txs[tx.Hash()] = tx
|
||||
t.addAuthorities(tx)
|
||||
}
|
||||
|
||||
// Remove removes a transaction from the lookup.
|
||||
|
|
@ -1704,6 +1739,7 @@ func (t *lookup) Remove(hash common.Hash) {
|
|||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
|
||||
t.removeAuthorities(hash)
|
||||
tx, ok := t.txs[hash]
|
||||
if !ok {
|
||||
log.Error("No transaction found to be deleted", "hash", hash)
|
||||
|
|
@ -1727,6 +1763,43 @@ func (t *lookup) TxsBelowTip(threshold *big.Int) types.Transactions {
|
|||
return found
|
||||
}
|
||||
|
||||
// addAuthorities tracks the supplied tx in relation to each authority it
|
||||
// specifies.
|
||||
func (t *lookup) addAuthorities(tx *types.Transaction) {
|
||||
for _, addr := range tx.SetCodeAuthorities() {
|
||||
list, ok := t.auths[addr]
|
||||
if !ok {
|
||||
list = []common.Hash{}
|
||||
}
|
||||
if slices.Contains(list, tx.Hash()) {
|
||||
// Don't add duplicates.
|
||||
continue
|
||||
}
|
||||
list = append(list, tx.Hash())
|
||||
t.auths[addr] = list
|
||||
}
|
||||
}
|
||||
|
||||
// removeAuthorities stops tracking the supplied tx in relation to its
|
||||
// authorities.
|
||||
func (t *lookup) removeAuthorities(hash common.Hash) {
|
||||
for addr := range t.auths {
|
||||
list := t.auths[addr]
|
||||
// Remove tx from tracker.
|
||||
if i := slices.Index(list, hash); i >= 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)
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
2
go.mod
2
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
|
||||
|
|
|
|||
4
go.sum
4
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=
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ func (t *StateTrie) Copy() *StateTrie {
|
|||
trie: *t.trie.Copy(),
|
||||
db: t.db,
|
||||
secKeyCache: t.secKeyCache,
|
||||
preimages: t.preimages,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue