diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 7924c521e8..0c673d15f1 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -17,7 +17,7 @@ jobs:
with:
go-version: 1.21.4
- name: Run tests
- run: go test ./...
+ run: go test -short ./...
env:
GOOS: linux
GOARCH: 386
diff --git a/.golangci.yml b/.golangci.yml
index 924e084431..84f79ee015 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -10,7 +10,6 @@ run:
linters:
disable-all: true
enable:
- - goconst
- goimports
- gosimple
- govet
@@ -37,9 +36,6 @@ linters:
linters-settings:
gofmt:
simplify: true
- goconst:
- min-len: 3 # minimum length of string constant
- min-occurrences: 6 # minimum number of occurrences
issues:
exclude-files:
diff --git a/Makefile b/Makefile
index e23161adf8..f2d0548cd8 100644
--- a/Makefile
+++ b/Makefile
@@ -38,11 +38,13 @@ generate-mocks:
go generate mockgen -destination=./eth/filters/IBackend.go -package=filters ./eth/filters Backend
go generate mockgen -destination=../eth/filters/IDatabase.go -package=filters ./ethdb Database
+#? geth: Build geth
geth:
$(GORUN) build/ci.go install ./cmd/geth
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."
+#? all: Build all packages and executables
all:
$(GORUN) build/ci.go install
@@ -89,6 +91,7 @@ goimports:
docs:
$(GORUN) cmd/clidoc/main.go -d ./docs/cli
+#? clean: Clean go cache, built executables, and the auto generated folder
clean:
go clean -cache
rm -fr build/_workspace/pkg/ $(GOBIN)/*
@@ -96,6 +99,7 @@ clean:
# The devtools target installs tools required for 'go generate'.
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
+#? devtools: Install recommended developer tools
devtools:
# Notice! If you adding new binary - add it also to tests/deps/fake.go file
$(GOBUILD) -o $(GOBIN)/stringer github.com/golang.org/x/tools/cmd/stringer
diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go
index 2e45e86ae2..38b3046970 100644
--- a/accounts/abi/bind/backend.go
+++ b/accounts/abi/bind/backend.go
@@ -84,6 +84,11 @@ type BlockHashContractCaller interface {
// used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide.
type ContractTransactor interface {
+ ethereum.GasEstimator
+ ethereum.GasPricer
+ ethereum.GasPricer1559
+ ethereum.TransactionSender
+
// HeaderByNumber returns a block header from the current canonical chain. If
// number is nil, the latest known header is returned.
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
@@ -93,38 +98,6 @@ type ContractTransactor interface {
// PendingNonceAt retrieves the current pending nonce associated with an account.
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
-
- // SuggestGasPrice retrieves the currently suggested gas price to allow a timely
- // execution of a transaction.
- SuggestGasPrice(ctx context.Context) (*big.Int, error)
-
- // SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow
- // a timely execution of a transaction.
- SuggestGasTipCap(ctx context.Context) (*big.Int, error)
-
- // EstimateGas tries to estimate the gas needed to execute a specific
- // transaction based on the current pending state of the backend blockchain.
- // There is no guarantee that this is the true gas limit requirement as other
- // transactions may be added or removed by miners, but it should provide a basis
- // for setting a reasonable default.
- EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
-
- // SendTransaction injects the transaction into the pending pool for execution.
- SendTransaction(ctx context.Context, tx *types.Transaction) error
-}
-
-// ContractFilterer defines the methods needed to access log events using one-off
-// queries or continuous event subscriptions.
-type ContractFilterer interface {
- // FilterLogs executes a log filter operation, blocking during execution and
- // returning all the results in one batch.
- //
- // TODO(karalabe): Deprecate when the subscription one can return past data too.
- FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)
-
- // SubscribeFilterLogs creates a background log filtering operation, returning
- // a subscription immediately, which can be used to stream the found events.
- SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
}
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
@@ -133,6 +106,12 @@ type DeployBackend interface {
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
}
+// ContractFilterer defines the methods needed to access log events using one-off
+// queries or continuous event subscriptions.
+type ContractFilterer interface {
+ ethereum.LogFilterer
+}
+
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
type ContractBackend interface {
ContractCaller
diff --git a/accounts/abi/bind/backends/bor_simulated.go b/accounts/abi/bind/backends/bor_simulated.go
index 18d2bc0f53..6ffe4881d0 100644
--- a/accounts/abi/bind/backends/bor_simulated.go
+++ b/accounts/abi/bind/backends/bor_simulated.go
@@ -5,18 +5,16 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
-func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
- number := rawdb.ReadHeaderNumber(fb.db, hash)
- if number == nil {
- return nil, nil
+func (b *SimulatedBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
+ receipt, err := b.GetBorBlockReceipt(ctx, hash)
+ if err != nil {
+ return nil, err
}
- receipt := rawdb.ReadRawBorReceipt(fb.db, hash, *number)
if receipt == nil {
return nil, nil
}
@@ -24,12 +22,12 @@ func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Has
return receipt, nil
}
-func (fb *filterBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
+func (b *SimulatedBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
return false, nil
}
-func (fb *filterBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
- receipt, err := fb.GetBorBlockReceipt(ctx, hash)
+func (b *SimulatedBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
+ receipt, err := b.GetBorBlockReceipt(ctx, hash)
if err != nil || receipt == nil {
return nil, err
}
@@ -38,6 +36,6 @@ func (fb *filterBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash)
}
// SubscribeStateSyncEvent subscribes to state sync events
-func (fb *filterBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
- return fb.bc.SubscribeStateSyncEvent(ch)
+func (b *SimulatedBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
+ return b.SubscribeStateSyncEvent(ch)
}
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index a51d0cba50..7c074ddf42 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -18,958 +18,36 @@ package backends
import (
"context"
- "errors"
- "fmt"
- "math/big"
- "sync"
- "time"
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/consensus/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/bloombits"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/eth/filters"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rpc"
+ "github.com/ethereum/go-ethereum/ethclient/simulated"
)
-// This nil assignment ensures at compile time that SimulatedBackend implements bind.ContractBackend.
-var _ bind.ContractBackend = (*SimulatedBackend)(nil)
-
-var (
- errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
- errBlockHashUnsupported = errors.New("simulatedBackend cannot access blocks by hash other than the latest block")
- errBlockDoesNotExist = errors.New("block does not exist in blockchain")
- errTransactionDoesNotExist = errors.New("transaction does not exist")
-)
-
-// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
-// the background. Its main purpose is to allow for easy testing of contract bindings.
-// Simulated backend implements the following interfaces:
-// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
-// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
+// SimulatedBackend is a simulated blockchain.
+// Deprecated: use package github.com/ethereum/go-ethereum/ethclient/simulated instead.
type SimulatedBackend struct {
- database ethdb.Database // In memory database to store our testing data
- blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
-
- mu sync.Mutex
- pendingBlock *types.Block // Currently pending block that will be imported on request
- pendingState *state.StateDB // Currently pending state that will be the active on request
- pendingReceipts types.Receipts // Currently receipts for the pending block
-
- events *filters.EventSystem // for filtering log events live
- filterSystem *filters.FilterSystem // for filtering database logs
-
- config *params.ChainConfig
+ *simulated.Backend
+ simulated.Client
}
-// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database
-// and uses a simulated blockchain for testing purposes.
-// A simulated backend always uses chainID 1337.
-func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
- genesis := core.Genesis{
- Config: params.AllEthashProtocolChanges,
- GasLimit: gasLimit,
- Alloc: alloc,
- }
- blockchain, _ := core.NewBlockChain(database, nil, &genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
-
- backend := &SimulatedBackend{
- database: database,
- blockchain: blockchain,
- config: genesis.Config,
- }
-
- filterBackend := &filterBackend{database, blockchain, backend}
- backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
- backend.events = filters.NewEventSystem(backend.filterSystem, false)
-
- header := backend.blockchain.CurrentBlock()
- block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
-
- backend.rollback(block)
- return backend
+// Fork sets the head to a new block, which is based on the provided parentHash.
+func (b *SimulatedBackend) Fork(ctx context.Context, parentHash common.Hash) error {
+ return b.Backend.Fork(parentHash)
}
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
+//
// A simulated backend always uses chainID 1337.
-func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
- return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit)
-}
-
-// Close terminates the underlying blockchain's update loop.
-func (b *SimulatedBackend) Close() error {
- b.blockchain.Stop()
- return nil
-}
-
-// Commit imports all the pending transactions as a single block and starts a
-// fresh new state.
-func (b *SimulatedBackend) Commit() common.Hash {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
- panic(err) // This cannot happen unless the simulator is wrong, fail in that case
- }
- blockHash := b.pendingBlock.Hash()
-
- // Using the last inserted block here makes it possible to build on a side
- // chain after a fork.
- b.rollback(b.pendingBlock)
-
- return blockHash
-}
-
-// Rollback aborts all pending transactions, reverting to the last committed state.
-func (b *SimulatedBackend) Rollback() {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- header := b.blockchain.CurrentBlock()
- block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
-
- b.rollback(block)
-}
-
-func (b *SimulatedBackend) rollback(parent *types.Block) {
- blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
-
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache(), nil)
-}
-
-// Fork creates a side-chain that can be used to simulate reorgs.
//
-// This function should be called with the ancestor block where the new side
-// chain should be started. Transactions (old and new) can then be applied on
-// top and Commit-ed.
-//
-// Note, the side-chain will only become canonical (and trigger the events) when
-// it becomes longer. Until then CallContract will still operate on the current
-// canonical chain.
-//
-// There is a % chance that the side chain becomes canonical at the same length
-// to simulate live network behavior.
-func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error {
- b.mu.Lock()
- defer b.mu.Unlock()
+// Deprecated: please use simulated.Backend from package
+// github.com/ethereum/go-ethereum/ethclient/simulated instead.
+func NewSimulatedBackend(alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
+ b := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(gasLimit))
- if len(b.pendingBlock.Transactions()) != 0 {
- return errors.New("pending block dirty")
- }
- block, err := b.blockByHash(ctx, parent)
- if err != nil {
- return err
- }
- b.rollback(block)
- return nil
-}
-
-// stateByBlockNumber retrieves a state by a given blocknumber.
-func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
- if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 {
- return b.blockchain.State()
- }
- block, err := b.blockByNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
- return b.blockchain.StateAt(block.Root())
-}
-
-// CodeAt returns the code associated with a certain account in the blockchain.
-func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
- return stateDB.GetCode(contract), nil
-}
-
-// CodeAtHash returns the code associated with a certain account in the blockchain.
-func (b *SimulatedBackend) CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- header, err := b.headerByHash(blockHash)
- if err != nil {
- return nil, err
- }
-
- stateDB, err := b.blockchain.StateAt(header.Root)
- if err != nil {
- return nil, err
- }
-
- return stateDB.GetCode(contract), nil
-}
-
-// BalanceAt returns the wei balance of a certain account in the blockchain.
-func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
- return stateDB.GetBalance(contract), nil
-}
-
-// NonceAt returns the nonce of a certain account in the blockchain.
-func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return 0, err
- }
- return stateDB.GetNonce(contract), nil
-}
-
-// StorageAt returns the value of key in the storage of an account in the blockchain.
-func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
- val := stateDB.GetState(contract, key)
- return val[:], nil
-}
-
-// TransactionReceipt returns the receipt of a transaction.
-func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config)
- if receipt == nil {
- return nil, ethereum.NotFound
- }
- return receipt, nil
-}
-
-// TransactionByHash checks the pool of pending transactions in addition to the
-// blockchain. The isPending return value indicates whether the transaction has been
-// mined yet. Note that the transaction may not be part of the canonical chain even if
-// it's not pending.
-func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- tx := b.pendingBlock.Transaction(txHash)
- if tx != nil {
- return tx, true, nil
- }
- tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash)
- if tx != nil {
- return tx, false, nil
- }
- return nil, false, ethereum.NotFound
-}
-
-// BlockByHash retrieves a block based on the block hash.
-func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.blockByHash(ctx, hash)
-}
-
-// blockByHash retrieves a block based on the block hash without Locking.
-func (b *SimulatedBackend) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- if hash == b.pendingBlock.Hash() {
- return b.pendingBlock, nil
- }
-
- block := b.blockchain.GetBlockByHash(hash)
- if block != nil {
- return block, nil
- }
-
- return nil, errBlockDoesNotExist
-}
-
-// BlockByNumber retrieves a block from the database by number, caching it
-// (associated with its hash) if found.
-func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.blockByNumber(ctx, number)
-}
-
-// blockByNumber retrieves a block from the database by number, caching it
-// (associated with its hash) if found without Lock.
-func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
- if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
- return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash())
- }
-
- block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
- if block == nil {
- return nil, errBlockDoesNotExist
- }
-
- return block, nil
-}
-
-// HeaderByHash returns a block header from the current canonical chain.
-func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
- return b.headerByHash(hash)
-}
-
-// headerByHash retrieves a header from the database by hash without Lock.
-func (b *SimulatedBackend) headerByHash(hash common.Hash) (*types.Header, error) {
- if hash == b.pendingBlock.Hash() {
- return b.pendingBlock.Header(), nil
- }
-
- header := b.blockchain.GetHeaderByHash(hash)
- if header == nil {
- return nil, errBlockDoesNotExist
- }
-
- return header, nil
-}
-
-// HeaderByNumber returns a block header from the current canonical chain. If number is
-// nil, the latest known header is returned.
-func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
- return b.blockchain.CurrentHeader(), nil
- }
-
- return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
-}
-
-// TransactionCount returns the number of transactions in a given block.
-func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockHash == b.pendingBlock.Hash() {
- return uint(b.pendingBlock.Transactions().Len()), nil
- }
-
- block := b.blockchain.GetBlockByHash(blockHash)
- if block == nil {
- return uint(0), errBlockDoesNotExist
- }
-
- return uint(block.Transactions().Len()), nil
-}
-
-// TransactionInBlock returns the transaction for a specific block at a specific index.
-func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockHash == b.pendingBlock.Hash() {
- transactions := b.pendingBlock.Transactions()
- if uint(len(transactions)) < index+1 {
- return nil, errTransactionDoesNotExist
- }
-
- return transactions[index], nil
- }
-
- block := b.blockchain.GetBlockByHash(blockHash)
- if block == nil {
- return nil, errBlockDoesNotExist
- }
-
- transactions := block.Transactions()
- if uint(len(transactions)) < index+1 {
- return nil, errTransactionDoesNotExist
- }
-
- return transactions[index], nil
-}
-
-// PendingCodeAt returns the code associated with an account in the pending state.
-func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.pendingState.GetCode(contract), nil
-}
-
-func newRevertError(result *core.ExecutionResult) *revertError {
- reason, errUnpack := abi.UnpackRevert(result.Revert())
- err := errors.New("execution reverted")
- if errUnpack == nil {
- err = fmt.Errorf("execution reverted: %v", reason)
- }
- return &revertError{
- error: err,
- reason: hexutil.Encode(result.Revert()),
+ return &SimulatedBackend{
+ Backend: b,
+ Client: b.Client(),
}
}
-
-// revertError is an API error that encompasses an EVM revert with JSON error
-// code and a binary data blob.
-type revertError struct {
- error
- reason string // revert reason hex encoded
-}
-
-// ErrorCode returns the JSON error code for a revert.
-// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
-func (e *revertError) ErrorCode() int {
- return 3
-}
-
-// ErrorData returns the hex encoded revert reason.
-func (e *revertError) ErrorData() interface{} {
- return e.reason
-}
-
-// CallContract executes a contract call.
-func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
- return nil, errBlockNumberUnsupported
- }
- return b.callContractAtHead(ctx, call)
-}
-
-// CallContractAtHash executes a contract call on a specific block hash.
-func (b *SimulatedBackend) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockHash != b.blockchain.CurrentBlock().Hash() {
- return nil, errBlockHashUnsupported
- }
- return b.callContractAtHead(ctx, call)
-}
-
-// callContractAtHead executes a contract call against the latest block state.
-func (b *SimulatedBackend) callContractAtHead(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
- stateDB, err := b.blockchain.State()
- if err != nil {
- return nil, err
- }
- res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB)
- if err != nil {
- return nil, err
- }
- // If the result contains a revert reason, try to unpack and return it.
- if len(res.Revert()) > 0 {
- return nil, newRevertError(res)
- }
- return res.Return(), res.Err
-}
-
-// PendingCallContract executes a contract call on the pending state.
-func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
- defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
-
- res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
- if err != nil {
- return nil, err
- }
- // If the result contains a revert reason, try to unpack and return it.
- if len(res.Revert()) > 0 {
- return nil, newRevertError(res)
- }
- return res.Return(), res.Err
-}
-
-// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving
-// the nonce currently pending for the account.
-func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
-}
-
-// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
-// chain doesn't have miners, we just return a gas price of 1 for any call.
-func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if b.pendingBlock.Header().BaseFee != nil {
- return b.pendingBlock.Header().BaseFee, nil
- }
- return big.NewInt(1), nil
-}
-
-// SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated
-// chain doesn't have miners, we just return a gas tip of 1 for any call.
-func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
- return big.NewInt(1), nil
-}
-
-// EstimateGas executes the requested code against the currently pending block/state and
-// returns the used amount of gas.
-func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- // Determine the lowest and highest possible gas limits to binary search in between
- var (
- lo uint64 = params.TxGas - 1
- hi uint64
- cap uint64
- )
- if call.Gas >= params.TxGas {
- hi = call.Gas
- } else {
- hi = b.pendingBlock.GasLimit()
- }
- // Normalize the max fee per gas the call is willing to spend.
- var feeCap *big.Int
- if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
- return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
- } else if call.GasPrice != nil {
- feeCap = call.GasPrice
- } else if call.GasFeeCap != nil {
- feeCap = call.GasFeeCap
- } else {
- feeCap = common.Big0
- }
- // Recap the highest gas allowance with account's balance.
- if feeCap.BitLen() != 0 {
- balance := b.pendingState.GetBalance(call.From) // from can't be nil
- available := new(big.Int).Set(balance)
- if call.Value != nil {
- if call.Value.Cmp(available) >= 0 {
- return 0, core.ErrInsufficientFundsForTransfer
- }
- available.Sub(available, call.Value)
- }
- allowance := new(big.Int).Div(available, feeCap)
- if allowance.IsUint64() && hi > allowance.Uint64() {
- transfer := call.Value
- if transfer == nil {
- transfer = new(big.Int)
- }
- log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
- "sent", transfer, "feecap", feeCap, "fundable", allowance)
- hi = allowance.Uint64()
- }
- }
- cap = hi
-
- // Create a helper to check if a gas allowance results in an executable transaction
- executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
- call.Gas = gas
-
- snapshot := b.pendingState.Snapshot()
- res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
- b.pendingState.RevertToSnapshot(snapshot)
-
- if err != nil {
- if errors.Is(err, core.ErrIntrinsicGas) {
- return true, nil, nil // Special case, raise gas limit
- }
- return true, nil, err // Bail out
- }
- return res.Failed(), res, nil
- }
- // Execute the binary search and hone in on an executable gas limit
- for lo+1 < hi {
- mid := (hi + lo) / 2
- failed, _, err := executable(mid)
-
- // If the error is not nil(consensus error), it means the provided message
- // call or transaction will never be accepted no matter how much gas it is
- // assigned. Return the error directly, don't struggle any more
- if err != nil {
- return 0, err
- }
- if failed {
- lo = mid
- } else {
- hi = mid
- }
- }
- // Reject the transaction as invalid if it still fails at the highest allowance
- if hi == cap {
- failed, result, err := executable(hi)
- if err != nil {
- return 0, err
- }
- if failed {
- if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) {
- if len(result.Revert()) > 0 {
- return 0, newRevertError(result)
- }
- return 0, result.Err
- }
- // Otherwise, the specified gas cap is too low
- return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
- }
- }
- return hi, nil
-}
-
-// callContract implements common code between normal and pending contract calls.
-// state is modified during execution, make sure to copy it if necessary.
-func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) {
- // Gas prices post 1559 need to be initialized
- if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
- return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
- }
- if !b.blockchain.Config().IsLondon(header.Number) {
- // If there's no basefee, then it must be a non-1559 execution
- if call.GasPrice == nil {
- call.GasPrice = new(big.Int)
- }
- call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
- } else {
- // A basefee is provided, necessitating 1559-type execution
- if call.GasPrice != nil {
- // User specified the legacy gas field, convert to 1559 gas typing
- call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
- } else {
- // User specified 1559 gas fields (or none), use those
- if call.GasFeeCap == nil {
- call.GasFeeCap = new(big.Int)
- }
- if call.GasTipCap == nil {
- call.GasTipCap = new(big.Int)
- }
- // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
- call.GasPrice = new(big.Int)
- if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
- call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
- }
- }
- }
- // Ensure message is initialized properly.
- if call.Gas == 0 {
- call.Gas = 10 * header.GasLimit
- }
- if call.Value == nil {
- call.Value = new(big.Int)
- }
-
- // Set infinite balance to the fake caller account.
- from := stateDB.GetOrNewStateObject(call.From)
- from.SetBalance(math.MaxBig256)
-
- // Execute the call.
- msg := &core.Message{
- From: call.From,
- To: call.To,
- Value: call.Value,
- GasLimit: call.Gas,
- GasPrice: call.GasPrice,
- GasFeeCap: call.GasFeeCap,
- GasTipCap: call.GasTipCap,
- Data: call.Data,
- AccessList: call.AccessList,
- SkipAccountChecks: true,
- }
-
- // Create a new environment which holds all relevant information
- // about the transaction and calling mechanisms.
- txContext := core.NewEVMTxContext(msg)
- evmContext := core.NewEVMBlockContext(header, b.blockchain, nil)
- vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
- gasPool := new(core.GasPool).AddGas(math.MaxUint64)
-
- return core.ApplyMessage(vmEnv, msg, gasPool, context.Background())
-}
-
-// SendTransaction updates the pending block to include the given transaction.
-func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- // Get the last block
- block, err := b.blockByHash(ctx, b.pendingBlock.ParentHash())
- if err != nil {
- return errors.New("could not fetch parent")
- }
- // Check transaction validity
- signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time())
- sender, err := types.Sender(signer, tx)
- if err != nil {
- return fmt.Errorf("invalid transaction: %v", err)
- }
- nonce := b.pendingState.GetNonce(sender)
- if tx.Nonce() != nonce {
- return fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)
- }
- // Include tx in chain
- blocks, receipts := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
- for _, tx := range b.pendingBlock.Transactions() {
- block.AddTxWithChain(b.blockchain, tx)
- }
- block.AddTxWithChain(b.blockchain, tx)
- })
- stateDB, err := b.blockchain.State()
- if err != nil {
- return err
- }
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
- b.pendingReceipts = receipts[0]
- return nil
-}
-
-// FilterLogs executes a log filter operation, blocking during execution and
-// returning all the results in one batch.
-//
-// TODO(karalabe): Deprecate when the subscription one can return past data too.
-func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) {
- var filter *filters.Filter
- if query.BlockHash != nil {
- // Block filter requested, construct a single-shot filter
- filter = b.filterSystem.NewBlockFilter(*query.BlockHash, query.Addresses, query.Topics)
- } else {
- // Initialize unset filter boundaries to run from genesis to chain head
- from := int64(0)
- if query.FromBlock != nil {
- from = query.FromBlock.Int64()
- }
- to := int64(-1)
- if query.ToBlock != nil {
- to = query.ToBlock.Int64()
- }
- // Construct the range filter
- filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics)
- }
- // Run the filter and return all the logs
- logs, err := filter.Logs(ctx)
- if err != nil {
- return nil, err
- }
- res := make([]types.Log, len(logs))
- for i, nLog := range logs {
- res[i] = *nLog
- }
- return res, nil
-}
-
-// SubscribeFilterLogs creates a background log filtering operation, returning a
-// subscription immediately, which can be used to stream the found events.
-func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
- // Subscribe to contract events
- sink := make(chan []*types.Log)
-
- sub, err := b.events.SubscribeLogs(query, sink)
- if err != nil {
- return nil, err
- }
- // Since we're getting logs in batches, we need to flatten them into a plain stream
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case logs := <-sink:
- for _, nlog := range logs {
- select {
- case ch <- *nlog:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-// SubscribeNewHead returns an event subscription for a new header.
-func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
- // subscribe to a new head
- sink := make(chan *types.Header)
- sub := b.events.SubscribeNewHeads(sink)
-
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case head := <-sink:
- select {
- case ch <- head:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-// AdjustTime adds a time shift to the simulated clock.
-// It can only be called on empty blocks.
-func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if len(b.pendingBlock.Transactions()) != 0 {
- return errors.New("could not adjust time on non-empty block")
- }
- // Get the last block
- block := b.blockchain.GetBlockByHash(b.pendingBlock.ParentHash())
- if block == nil {
- return errors.New("could not find parent")
- }
-
- blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
- block.OffsetTime(int64(adjustment.Seconds()))
- })
- stateDB, err := b.blockchain.State()
- if err != nil {
- return err
- }
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
- return nil
-}
-
-// Blockchain returns the underlying blockchain.
-func (b *SimulatedBackend) Blockchain() *core.BlockChain {
- return b.blockchain
-}
-
-// filterBackend implements filters.Backend to support filtering for logs without
-// taking bloom-bits acceleration structures into account.
-type filterBackend struct {
- db ethdb.Database
- bc *core.BlockChain
- backend *SimulatedBackend
-}
-
-func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
-
-func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
-
-func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
- switch number {
- case rpc.PendingBlockNumber:
- if block := fb.backend.pendingBlock; block != nil {
- return block.Header(), nil
- }
- return nil, nil
- case rpc.LatestBlockNumber:
- return fb.bc.CurrentHeader(), nil
- case rpc.FinalizedBlockNumber:
- return fb.bc.CurrentFinalBlock(), nil
- case rpc.SafeBlockNumber:
- return fb.bc.CurrentSafeBlock(), nil
- default:
- return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil
- }
-}
-
-func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
- return fb.bc.GetHeaderByHash(hash), nil
-}
-
-func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
- if body := fb.bc.GetBody(hash); body != nil {
- return body, nil
- }
- return nil, errors.New("block body not found")
-}
-
-func (fb *filterBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- return fb.backend.pendingBlock, fb.backend.pendingReceipts
-}
-
-func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
- number := rawdb.ReadHeaderNumber(fb.db, hash)
- if number == nil {
- return nil, nil
- }
- header := rawdb.ReadHeader(fb.db, hash, *number)
- if header == nil {
- return nil, nil
- }
- return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil
-}
-
-func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
- logs := rawdb.ReadLogs(fb.db, hash, number)
- return logs, nil
-}
-
-func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
- return nullSubscription()
-}
-
-func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
- return fb.bc.SubscribeChainEvent(ch)
-}
-
-func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
- return fb.bc.SubscribeRemovedLogsEvent(ch)
-}
-
-func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
- return fb.bc.SubscribeLogsEvent(ch)
-}
-
-func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
- return nullSubscription()
-}
-
-func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
-
-func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) {
- panic("not supported")
-}
-
-func (fb *filterBackend) ChainConfig() *params.ChainConfig {
- panic("not supported")
-}
-
-func (fb *filterBackend) CurrentHeader() *types.Header {
- panic("not supported")
-}
-
-func nullSubscription() event.Subscription {
- return event.NewSubscription(func(quit <-chan struct{}) error {
- <-quit
- return nil
- })
-}
diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go
deleted file mode 100644
index f7c910adb4..0000000000
--- a/accounts/abi/bind/backends/simulated_test.go
+++ /dev/null
@@ -1,1607 +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 backends
-
-import (
- "bytes"
- "context"
- "errors"
- "math/big"
- "math/rand"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "go.uber.org/goleak"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/leak"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/params"
-)
-
-func TestSimulatedBackend(t *testing.T) {
- defer goleak.VerifyNone(t, leak.IgnoreList()...)
- var gasLimit uint64 = 8000029
-
- key, _ := crypto.GenerateKey() // nolint: gosec
- auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- genAlloc := make(core.GenesisAlloc)
- genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)}
-
- sim := NewSimulatedBackend(genAlloc, gasLimit)
- defer sim.Close()
-
- // should return an error if the tx is not found
- txHash := common.HexToHash("2")
- _, isPending, err := sim.TransactionByHash(context.Background(), txHash)
-
- if isPending {
- t.Fatal("transaction should not be pending")
- }
-
- if err != ethereum.NotFound {
- t.Fatalf("err should be `ethereum.NotFound` but received %v", err)
- }
-
- // generate a transaction and confirm you can retrieve it
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- code := `6060604052600a8060106000396000f360606040526008565b00`
-
- var gas uint64 = 3000000
- tx := types.NewContractCreation(0, big.NewInt(0), gas, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key)
-
- err = sim.SendTransaction(context.Background(), tx)
- if err != nil {
- t.Fatal("error sending transaction")
- }
-
- txHash = tx.Hash()
- _, isPending, err = sim.TransactionByHash(context.Background(), txHash)
-
- if err != nil {
- t.Fatalf("error getting transaction with hash: %v", txHash.String())
- }
-
- if !isPending {
- t.Fatal("transaction should have pending status")
- }
-
- sim.Commit()
-
- _, isPending, err = sim.TransactionByHash(context.Background(), txHash)
- if err != nil {
- t.Fatalf("error getting transaction with hash: %v", txHash.String())
- }
-
- if isPending {
- t.Fatal("transaction should not have pending status")
- }
-}
-
-var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
-
-// the following is based on this contract:
-//
-// contract T {
-// event received(address sender, uint amount, bytes memo);
-// event receivedAddr(address sender);
-//
-// function receive(bytes calldata memo) external payable returns (string memory res) {
-// emit received(msg.sender, msg.value, memo);
-// emit receivedAddr(msg.sender);
-// return "hello world";
-// }
-// }
-const abiJSON = `[ { "constant": false, "inputs": [ { "name": "memo", "type": "bytes" } ], "name": "receive", "outputs": [ { "name": "res", "type": "string" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" }, { "indexed": false, "name": "amount", "type": "uint256" }, { "indexed": false, "name": "memo", "type": "bytes" } ], "name": "received", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" } ], "name": "receivedAddr", "type": "event" } ]`
-const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
-const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
-
-// expected return value contains "hello world"
-var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-
-func simTestBackend(testAddr common.Address) *SimulatedBackend {
- return NewSimulatedBackend(
- core.GenesisAlloc{
- testAddr: {Balance: big.NewInt(10000000000000000)},
- }, 10000000,
- )
-}
-
-func TestNewSimulatedBackend(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- expectedBal := big.NewInt(10000000000000000)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- if sim.config != params.AllEthashProtocolChanges {
- t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config)
- }
-
- if sim.blockchain.Config() != params.AllEthashProtocolChanges {
- t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config)
- }
-
- stateDB, _ := sim.blockchain.State()
-
- bal := stateDB.GetBalance(testAddr)
- if bal.Cmp(expectedBal) != 0 {
- t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
- }
-}
-
-func TestAdjustTime(t *testing.T) {
- t.Parallel()
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
-
- prevTime := sim.pendingBlock.Time()
-
- if err := sim.AdjustTime(time.Second); err != nil {
- t.Error(err)
- }
-
- newTime := sim.pendingBlock.Time()
-
- if newTime-prevTime != uint64(time.Second.Seconds()) {
- t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime)
- }
-}
-
-func TestNewAdjustTimeFail(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.blockchain.Stop()
-
- // Create tx and send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- sim.SendTransaction(context.Background(), signedTx)
- // AdjustTime should fail on non-empty block
- if err := sim.AdjustTime(time.Second); err == nil {
- t.Error("Expected adjust time to error on non-empty block")
- }
-
- sim.Commit()
-
- prevTime := sim.pendingBlock.Time()
-
- if err := sim.AdjustTime(time.Minute); err != nil {
- t.Error(err)
- }
-
- newTime := sim.pendingBlock.Time()
- if newTime-prevTime != uint64(time.Minute.Seconds()) {
- t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime)
- }
- // Put a transaction after adjusting time
- tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- sim.SendTransaction(context.Background(), signedTx2)
- sim.Commit()
-
- newTime = sim.pendingBlock.Time()
- if newTime-prevTime >= uint64(time.Minute.Seconds()) {
- t.Errorf("time adjusted, but shouldn't be: prev: %v, new: %v", prevTime, newTime)
- }
-}
-
-func TestBalanceAt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- expectedBal := big.NewInt(10000000000000000)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- bal, err := sim.BalanceAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Error(err)
- }
-
- if bal.Cmp(expectedBal) != 0 {
- t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
- }
-}
-
-func TestBlockByHash(t *testing.T) {
- t.Parallel()
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
-
- bgCtx := context.Background()
-
- block, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- blockByHash, err := sim.BlockByHash(bgCtx, block.Hash())
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if block.Hash() != blockByHash.Hash() {
- t.Errorf("did not get expected block")
- }
-}
-
-func TestBlockByNumber(t *testing.T) {
- t.Parallel()
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
-
- bgCtx := context.Background()
-
- block, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if block.NumberU64() != 0 {
- t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
- }
-
- // create one block
- sim.Commit()
-
- block, err = sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if block.NumberU64() != 1 {
- t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
- }
-
- blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block by number: %v", err)
- }
-
- if blockByNumber.Hash() != block.Hash() {
- t.Errorf("did not get the same block with height of 1 as before")
- }
-}
-
-func TestNonceAt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0))
- if err != nil {
- t.Errorf("could not get nonce for test addr: %v", err)
- }
-
- if nonce != uint64(0) {
- t.Errorf("received incorrect nonce. expected 0, got %v", nonce)
- }
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get nonce for test addr: %v", err)
- }
-
- if newNonce != nonce+uint64(1) {
- t.Errorf("received incorrect nonce. expected 1, got %v", nonce)
- }
- // create some more blocks
- sim.Commit()
- // Check that we can get data for an older block/state
- newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
- if err != nil {
- t.Fatalf("could not get nonce for test addr: %v", err)
- }
-
- if newNonce != nonce+uint64(1) {
- t.Fatalf("received incorrect nonce. expected 1, got %v", nonce)
- }
-}
-
-func TestSendTransaction(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block at height 1: %v", err)
- }
-
- if signedTx.Hash() != block.Transactions()[0].Hash() {
- t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
- }
-}
-
-func TestTransactionByHash(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := NewSimulatedBackend(
- core.GenesisAlloc{
- testAddr: {Balance: big.NewInt(10000000000000000)},
- }, 10000000,
- )
- defer sim.Close()
-
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- // ensure tx is committed pending
- receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
- }
-
- if !pending {
- t.Errorf("expected transaction to be in pending state")
- }
-
- if receivedTx.Hash() != signedTx.Hash() {
- t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
- }
-
- sim.Commit()
-
- // ensure tx is not and committed pending
- receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
- }
-
- if pending {
- t.Errorf("expected transaction to not be in pending state")
- }
-
- if receivedTx.Hash() != signedTx.Hash() {
- t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
- }
-}
-
-func TestEstimateGas(t *testing.T) {
- t.Parallel()
- /*
- pragma solidity ^0.6.4;
- contract GasEstimation {
- function PureRevert() public { revert(); }
- function Revert() public { revert("revert reason");}
- function OOG() public { for (uint i = 0; ; i++) {}}
- function Assert() public { assert(false);}
- function Valid() public {}
- }
- */
- const contractAbi = "[{\"inputs\":[],\"name\":\"Assert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OOG\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PureRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Revert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Valid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
-
- const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033"
-
- key, _ := crypto.GenerateKey()
- addr := crypto.PubkeyToAddress(key.PublicKey)
- opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
-
- sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000)
- defer sim.Close()
-
- parsed, _ := abi.JSON(strings.NewReader(contractAbi))
- contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim)
- sim.Commit()
-
- var cases = []struct {
- name string
- message ethereum.CallMsg
- expect uint64
- expectError error
- expectData interface{}
- }{
- {"plain transfer(valid)", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(1),
- Data: nil,
- }, params.TxGas, nil, nil},
-
- {"plain transfer(invalid)", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(1),
- Data: nil,
- }, 0, errors.New("execution reverted"), nil},
-
- {"Revert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("d8b98391"),
- }, 0, errors.New("execution reverted: revert reason"), "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"},
-
- {"PureRevert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("aa8b1d30"),
- }, 0, errors.New("execution reverted"), nil},
-
- {"OOG", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("50f6fe34"),
- }, 0, errors.New("gas required exceeds allowance (100000)"), nil},
-
- {"Assert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("b9b046f9"),
- }, 0, errors.New("invalid opcode: INVALID"), nil},
-
- {"Valid", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("e09fface"),
- }, 21275, nil, nil},
- }
-
- for _, c := range cases {
- got, err := sim.EstimateGas(context.Background(), c.message)
- if c.expectError != nil {
- if err == nil {
- t.Fatalf("Expect error, got nil")
- }
-
- if c.expectError.Error() != err.Error() {
- t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
- }
-
- if c.expectData != nil {
- if err, ok := err.(*revertError); !ok {
- t.Fatalf("Expect revert error, got %T", err)
- } else if !reflect.DeepEqual(err.ErrorData(), c.expectData) {
- t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.ErrorData())
- }
- }
-
- continue
- }
-
- if got != c.expect {
- t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
- }
- }
-}
-
-func TestEstimateGasWithPrice(t *testing.T) {
- t.Parallel()
- key, _ := crypto.GenerateKey()
- addr := crypto.PubkeyToAddress(key.PublicKey)
-
- sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000)
- defer sim.Close()
-
- recipient := common.HexToAddress("deadbeef")
-
- var cases = []struct {
- name string
- message ethereum.CallMsg
- expect uint64
- expectError error
- }{
- {"EstimateWithoutPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(100000000000),
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithVeryHighPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(1e14), // gascost = 2.1ether
- Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithSuperhighPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(2e14), // gascost = 4.2ether
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
-
- {"EstimateEIP1559WithHighFees", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
- GasTipCap: big.NewInt(1),
- Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, params.TxGas, nil},
-
- {"EstimateEIP1559WithSuperHighFees", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
- GasTipCap: big.NewInt(1),
- Value: big.NewInt(1e17 + 1), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, params.TxGas, errors.New("gas required exceeds allowance (20999)")}, // 20999=(2.2ether-0.1ether-1wei)/(1e14)
- }
-
- for i, c := range cases {
- got, err := sim.EstimateGas(context.Background(), c.message)
- if c.expectError != nil {
- if err == nil {
- t.Fatalf("test %d: expect error, got nil", i)
- }
-
- if c.expectError.Error() != err.Error() {
- t.Fatalf("test %d: expect error, want %v, got %v", i, c.expectError, err)
- }
-
- continue
- }
-
- if c.expectError == nil && err != nil {
- t.Fatalf("test %d: didn't expect error, got %v", i, err)
- }
-
- if got != c.expect {
- t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
- }
- }
-}
-
-func TestHeaderByHash(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- header, err := sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash())
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if header.Hash() != headerByHash.Hash() {
- t.Errorf("did not get expected block")
- }
-}
-
-func TestHeaderByNumber(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
-
- if latestBlockHeader == nil {
- t.Errorf("received a nil block header")
- } else if latestBlockHeader.Number.Uint64() != uint64(0) {
- t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64())
- }
-
- sim.Commit()
-
- latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for blockheight of 1: %v", err)
- }
-
- blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get header for blockheight of 1: %v", err)
- }
-
- if blockHeader.Hash() != latestBlockHeader.Hash() {
- t.Errorf("block header and latest block header are not the same")
- }
-
- if blockHeader.Number.Int64() != int64(1) {
- t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64())
- }
-
- block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block for blockheight of 1: %v", err)
- }
-
- if block.Hash() != blockHeader.Hash() {
- t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash())
- }
-}
-
-func TestTransactionCount(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- currentBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil || currentBlock == nil {
- t.Error("could not get current block")
- }
-
- count, err := sim.TransactionCount(bgCtx, currentBlock.Hash())
- if err != nil {
- t.Error("could not get current block's transaction count")
- }
-
- if count != 0 {
- t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count)
- }
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- lastBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
-
- count, err = sim.TransactionCount(bgCtx, lastBlock.Hash())
- if err != nil {
- t.Error("could not get current block's transaction count")
- }
-
- if count != 1 {
- t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count)
- }
-}
-
-func TestTransactionInBlock(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0))
- if err == nil && err != errTransactionDoesNotExist {
- t.Errorf("expected a transaction does not exist error to be received but received %v", err)
- }
-
- if transaction != nil {
- t.Errorf("expected transaction to be nil but received %v", transaction)
- }
-
- // expect pending nonce to be 0 since account has not been used
- pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(0) {
- t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
- }
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- lastBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
-
- transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1))
- if err == nil && err != errTransactionDoesNotExist {
- t.Errorf("expected a transaction does not exist error to be received but received %v", err)
- }
-
- if transaction != nil {
- t.Errorf("expected transaction to be nil but received %v", transaction)
- }
-
- transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0))
- if err != nil {
- t.Errorf("could not get transaction in the latest block with hash %v: %v", lastBlock.Hash().String(), err)
- }
-
- if signedTx.Hash().String() != transaction.Hash().String() {
- t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String())
- }
-}
-
-func TestPendingNonceAt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- // expect pending nonce to be 0 since account has not been used
- pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(0) {
- t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
- }
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- // expect pending nonce to be 1 since account has submitted one transaction
- pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(1) {
- t.Errorf("expected pending nonce of 1 got %v", pendingNonce)
- }
-
- // make a new transaction with a nonce of 1
- tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not send tx: %v", err)
- }
-
- // expect pending nonce to be 2 since account now has two transactions
- pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(2) {
- t.Errorf("expected pending nonce of 2 got %v", pendingNonce)
- }
-}
-
-func TestTransactionReceipt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
-
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction receipt: %v", err)
- }
-
- if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() {
- t.Errorf("received receipt is not correct: %v", receipt)
- }
-}
-
-func TestSuggestGasPrice(t *testing.T) {
- t.Parallel()
- sim := NewSimulatedBackend(
- core.GenesisAlloc{},
- 10000000,
- )
- defer sim.Close()
-
- bgCtx := context.Background()
-
- gasPrice, err := sim.SuggestGasPrice(bgCtx)
- if err != nil {
- t.Errorf("could not get gas price: %v", err)
- }
-
- if gasPrice.Uint64() != sim.pendingBlock.Header().BaseFee.Uint64() {
- t.Errorf("gas price was not expected value of %v. actual: %v", sim.pendingBlock.Header().BaseFee.Uint64(), gasPrice.Uint64())
- }
-}
-
-func TestPendingCodeAt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- code, err := sim.CodeAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- if len(code) != 0 {
- t.Errorf("got code for account that does not have contract code")
- }
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
-
- contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
- }
-
- code, err = sim.PendingCodeAt(bgCtx, contractAddr)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- if len(code) == 0 {
- t.Errorf("did not get code for account that has contract code")
- }
- // ensure code received equals code deployed
- if !bytes.Equal(code, common.FromHex(deployedCode)) {
- t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
- }
-}
-
-func TestCodeAt(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- code, err := sim.CodeAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- if len(code) != 0 {
- t.Errorf("got code for account that does not have contract code")
- }
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
-
- contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
- }
-
- sim.Commit()
-
- code, err = sim.CodeAt(bgCtx, contractAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- if len(code) == 0 {
- t.Errorf("did not get code for account that has contract code")
- }
- // ensure code received equals code deployed
- if !bytes.Equal(code, common.FromHex(deployedCode)) {
- t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
- }
-}
-
-func TestCodeAtHash(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
- code, err := sim.CodeAtHash(bgCtx, testAddr, sim.Blockchain().CurrentHeader().Hash())
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) != 0 {
- t.Errorf("got code for account that does not have contract code")
- }
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
- }
-
- blockHash := sim.Commit()
- code, err = sim.CodeAtHash(bgCtx, contractAddr, blockHash)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) == 0 {
- t.Errorf("did not get code for account that has contract code")
- }
- // ensure code received equals code deployed
- if !bytes.Equal(code, common.FromHex(deployedCode)) {
- t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
- }
-}
-
-// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
-//
-// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
-func TestPendingAndCallContract(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
-
- addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v", err)
- }
-
- input, err := parsed.Pack("receive", []byte("X"))
- if err != nil {
- t.Errorf("could not pack receive function on contract: %v", err)
- }
-
- // make sure you can call the contract in pending state
- res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- })
- if err != nil {
- t.Errorf("could not call receive method on contract: %v", err)
- }
-
- if len(res) == 0 {
- t.Errorf("result of contract call was empty: %v", res)
- }
-
- // while comparing against the byte array is more exact, also compare against the human readable string for readability
- if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
- t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
- }
-
- blockHash := sim.Commit()
-
- // make sure you can call the contract
- res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- }, nil)
- if err != nil {
- t.Errorf("could not call receive method on contract: %v", err)
- }
-
- if len(res) == 0 {
- t.Errorf("result of contract call was empty: %v", res)
- }
-
- if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
- t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
- }
-
- // make sure you can call the contract by hash
- res, err = sim.CallContractAtHash(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- }, blockHash)
- if err != nil {
- t.Errorf("could not call receive method on contract: %v", err)
- }
- if len(res) == 0 {
- t.Errorf("result of contract call was empty: %v", res)
- }
-
- if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
- t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
- }
-}
-
-// This test is based on the following contract:
-/*
-contract Reverter {
- function revertString() public pure{
- require(false, "some error");
- }
- function revertNoString() public pure {
- require(false, "");
- }
- function revertASM() public pure {
- assembly {
- revert(0x0, 0x0)
- }
- }
- function noRevert() public pure {
- assembly {
- // Assembles something that looks like require(false, "some error") but is not reverted
- mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
- mstore(0x4, 0x0000000000000000000000000000000000000000000000000000000000000020)
- mstore(0x24, 0x000000000000000000000000000000000000000000000000000000000000000a)
- mstore(0x44, 0x736f6d65206572726f7200000000000000000000000000000000000000000000)
- return(0x0, 0x64)
- }
- }
-}*/
-func TestCallContractRevert(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- bgCtx := context.Background()
-
- reverterABI := `[{"inputs": [],"name": "noRevert","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertASM","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertNoString","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertString","outputs": [],"stateMutability": "pure","type": "function"}]`
- reverterBin := "608060405234801561001057600080fd5b506101d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b409e01146100515780639b340e361461005b5780639bd6103714610065578063b7246fc11461006f575b600080fd5b610059610079565b005b6100636100ca565b005b61006d6100cf565b005b610077610145565b005b60006100c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526000815260200160200191505060405180910390fd5b565b600080fd5b6000610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f736f6d65206572726f720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f736f6d65206572726f720000000000000000000000000000000000000000000060445260646000f3fea2646970667358221220cdd8af0609ec4996b7360c7c780bad5c735740c64b1fffc3445aa12d37f07cb164736f6c63430006070033"
-
- parsed, err := abi.JSON(strings.NewReader(reverterABI))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
-
- contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
-
- addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(reverterBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v", err)
- }
-
- inputs := make(map[string]interface{}, 3)
- inputs["revertASM"] = nil
- inputs["revertNoString"] = ""
- inputs["revertString"] = "some error"
-
- call := make([]func([]byte) ([]byte, error), 2)
- call[0] = func(input []byte) ([]byte, error) {
- return sim.PendingCallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- })
- }
- call[1] = func(input []byte) ([]byte, error) {
- return sim.CallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- }, nil)
- }
-
- // Run pending calls then commit
- for _, cl := range call {
- for key, val := range inputs {
- input, err := parsed.Pack(key)
- if err != nil {
- t.Errorf("could not pack %v function on contract: %v", key, err)
- }
-
- res, err := cl(input)
- if err == nil {
- t.Errorf("call to %v was not reverted", key)
- }
-
- if res != nil {
- t.Errorf("result from %v was not nil: %v", key, res)
- }
-
- if val != nil {
- rerr, ok := err.(*revertError)
- if !ok {
- t.Errorf("expect revert error")
- }
-
- if rerr.Error() != "execution reverted: "+val.(string) {
- t.Errorf("error was malformed: got %v want %v", rerr.Error(), val)
- }
- } else {
- // revert(0x0,0x0)
- if err.Error() != "execution reverted" {
- t.Errorf("error was malformed: got %v want %v", err, "execution reverted")
- }
- }
- }
-
- input, err := parsed.Pack("noRevert")
- if err != nil {
- t.Errorf("could not pack noRevert function on contract: %v", err)
- }
-
- res, err := cl(input)
- if err != nil {
- t.Error("call to noRevert was reverted")
- }
-
- if res == nil {
- t.Errorf("result from noRevert was nil")
- }
-
- sim.Commit()
- }
-}
-
-// TestFork check that the chain length after a reorg is correct.
-// Steps:
-// 1. Save the current block which will serve as parent for the fork.
-// 2. Mine n blocks with n ∈ [0, 20].
-// 3. Assert that the chain length is n.
-// 4. Fork by using the parent block as ancestor.
-// 5. Mine n+1 blocks which should trigger a reorg.
-// 6. Assert that the chain length is n+1.
-// Since Commit() was called 2n+1 times in total,
-// having a chain length of just n+1 means that a reorg occurred.
-func TestFork(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parent := sim.blockchain.CurrentBlock()
- // 2.
- n := int(rand.Int31n(21))
- for i := 0; i < n; i++ {
- sim.Commit()
- }
- // 3.
- if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n) {
- t.Error("wrong chain length")
- }
- // 4.
- sim.Fork(context.Background(), parent.Hash())
- // 5.
- for i := 0; i < n+1; i++ {
- sim.Commit()
- }
- // 6.
- if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n+1) {
- t.Error("wrong chain length")
- }
-}
-
-/*
-Example contract to test event emission:
-
- pragma solidity >=0.7.0 <0.9.0;
- contract Callable {
- event Called();
- function Call() public { emit Called(); }
- }
-*/
-const callableAbi = "[{\"anonymous\":false,\"inputs\":[],\"name\":\"Called\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"Call\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
-
-const callableBin = "6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806334e2292114602d575b600080fd5b60336035565b005b7f81fab7a4a0aa961db47eefc81f143a5220e8c8495260dd65b1356f1d19d3c7b860405160405180910390a156fea2646970667358221220029436d24f3ac598ceca41d4d712e13ced6d70727f4cdc580667de66d2f51d8b64736f6c63430008010033"
-
-// TestForkLogsReborn check that the simulated reorgs
-// correctly remove and reborn logs.
-// Steps:
-// 1. Deploy the Callable contract.
-// 2. Set up an event subscription.
-// 3. Save the current block which will serve as parent for the fork.
-// 4. Send a transaction.
-// 5. Check that the event was included.
-// 6. Fork by using the parent block as ancestor.
-// 7. Mine two blocks to trigger a reorg.
-// 8. Check that the event was removed.
-// 9. Re-send the transaction and mine a block.
-// 10. Check that the event was reborn.
-func TestForkLogsReborn(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parsed, _ := abi.JSON(strings.NewReader(callableAbi))
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
-
- _, _, contract, err := bind.DeployContract(auth, parsed, common.FromHex(callableBin), sim)
- if err != nil {
- t.Errorf("deploying contract: %v", err)
- }
-
- sim.Commit()
- // 2.
- logs, sub, err := contract.WatchLogs(nil, "Called")
- if err != nil {
- t.Errorf("watching logs: %v", err)
- }
- defer sub.Unsubscribe()
- // 3.
- parent := sim.blockchain.CurrentBlock()
- // 4.
- tx, err := contract.Transact(auth, "Call")
- if err != nil {
- t.Errorf("transacting: %v", err)
- }
-
- sim.Commit()
- // 5.
- log := <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
-
- if log.Removed {
- t.Error("Event should be included")
- }
- // 6.
- if err := sim.Fork(context.Background(), parent.Hash()); err != nil {
- t.Errorf("forking: %v", err)
- }
- // 7.
- sim.Commit()
- sim.Commit()
- // 8.
- log = <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
-
- if !log.Removed {
- t.Error("Event should be removed")
- }
- // 9.
- if err := sim.SendTransaction(context.Background(), tx); err != nil {
- t.Errorf("sending transaction: %v", err)
- }
-
- sim.Commit()
- // 10.
- log = <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
-
- if log.Removed {
- t.Error("Event should be included")
- }
-}
-
-// TestForkResendTx checks that re-sending a TX after a fork
-// is possible and does not cause a "nonce mismatch" panic.
-// Steps:
-// 1. Save the current block which will serve as parent for the fork.
-// 2. Send a transaction.
-// 3. Check that the TX is included in block 1.
-// 4. Fork by using the parent block as ancestor.
-// 5. Mine a block, Re-send the transaction and mine another one.
-// 6. Check that the TX is now included in block 2.
-func TestForkResendTx(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parent := sim.blockchain.CurrentBlock()
- // 2.
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
- sim.SendTransaction(context.Background(), tx)
- sim.Commit()
- // 3.
- receipt, _ := sim.TransactionReceipt(context.Background(), tx.Hash())
- if h := receipt.BlockNumber.Uint64(); h != 1 {
- t.Errorf("TX included in wrong block: %d", h)
- }
- // 4.
- if err := sim.Fork(context.Background(), parent.Hash()); err != nil {
- t.Errorf("forking: %v", err)
- }
- // 5.
- sim.Commit()
-
- if err := sim.SendTransaction(context.Background(), tx); err != nil {
- t.Errorf("sending transaction: %v", err)
- }
-
- sim.Commit()
- // 6.
- receipt, _ = sim.TransactionReceipt(context.Background(), tx.Hash())
- if h := receipt.BlockNumber.Uint64(); h != 2 {
- t.Errorf("TX included in wrong block: %d", h)
- }
-}
-
-func TestCommitReturnValue(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
-
- defer sim.Close()
-
- startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
-
- // Test if Commit returns the correct block hash
- h1 := sim.Commit()
- if h1 != sim.blockchain.CurrentBlock().Hash() {
- t.Error("Commit did not return the hash of the last block.")
- }
-
- // Create a block in the original chain (containing a transaction to force different block hashes)
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
- _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
- _ = sim.SendTransaction(context.Background(), tx)
- h2 := sim.Commit()
-
- // Create another block in the original chain
- sim.Commit()
-
- // Fork at the first bock
- if err := sim.Fork(context.Background(), h1); err != nil {
- t.Errorf("forking: %v", err)
- }
-
- // Test if Commit returns the correct block hash after the reorg
- h2fork := sim.Commit()
- if h2 == h2fork {
- t.Error("The block in the fork and the original block are the same block!")
- }
-
- if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil {
- t.Error("Could not retrieve the just created block (side-chain)")
- }
-}
-
-// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
-// block's parent rather than the canonical head's parent.
-func TestAdjustTimeAfterFork(t *testing.T) {
- t.Parallel()
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
-
- defer sim.Close()
-
- sim.Commit() // h1
- h1 := sim.blockchain.CurrentHeader().Hash()
- sim.Commit() // h2
- _ = sim.Fork(context.Background(), h1)
- _ = sim.AdjustTime(1 * time.Second)
- sim.Commit()
-
- head := sim.blockchain.CurrentHeader()
- if head.Number == common.Big2 && head.ParentHash != h1 {
- t.Errorf("failed to build block on fork")
- }
-}
diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go
index 318247b6cf..4ee6ea78e6 100644
--- a/accounts/abi/bind/bind_test.go
+++ b/accounts/abi/bind/bind_test.go
@@ -289,7 +289,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -297,7 +297,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy an interaction tester contract and call a transaction on it
@@ -305,6 +305,7 @@ var bindTests = []struct {
if err != nil {
t.Fatalf("Failed to deploy interactor contract: %v", err)
}
+ sim.Commit()
if _, err := interactor.Transact(auth, "Transact string"); err != nil {
t.Fatalf("Failed to transact with interactor contract: %v", err)
}
@@ -344,7 +345,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -352,7 +353,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a tuple tester contract and execute a structured call on it
@@ -390,7 +391,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -398,7 +399,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a tuple tester contract and execute a structured call on it
@@ -448,7 +449,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -456,7 +457,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a slice tester contract and execute a n array call on it
@@ -496,7 +497,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -504,7 +505,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a default method invoker contract and execute its default method
@@ -512,6 +513,7 @@ var bindTests = []struct {
if err != nil {
t.Fatalf("Failed to deploy defaulter contract: %v", err)
}
+ sim.Commit()
if _, err := (&DefaulterRaw{defaulter}).Transfer(auth); err != nil {
t.Fatalf("Failed to invoke default method: %v", err)
}
@@ -562,7 +564,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -570,7 +572,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a structs method invoker contract and execute its default method
@@ -608,12 +610,12 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
`,
`
// Create a simulator and wrap a non-deployed contract
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{}, uint64(10000000000))
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{}, uint64(10000000000))
defer sim.Close()
nonexistent, err := NewNonExistent(common.Address{}, sim)
@@ -647,12 +649,12 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
`,
`
// Create a simulator and wrap a non-deployed contract
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{}, uint64(10000000000))
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{}, uint64(10000000000))
defer sim.Close()
nonexistent, err := NewNonExistentStruct(common.Address{}, sim)
@@ -694,7 +696,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -702,7 +704,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a funky gas pattern contract
@@ -744,7 +746,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -752,7 +754,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a sender tester contract and execute a structured call on it
@@ -819,7 +821,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -827,7 +829,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a underscorer tester contract and execute a structured call on it
@@ -913,7 +915,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -921,7 +923,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy an eventer contract
@@ -1103,7 +1105,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -1111,7 +1113,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
//deploy the test contract
@@ -1238,7 +1240,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
@@ -1246,7 +1248,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
_, _, contract, err := DeployTuple(auth, sim)
@@ -1380,7 +1382,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -1388,7 +1390,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
//deploy the test contract
@@ -1446,14 +1448,14 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
// Initialize test accounts
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// deploy the test contract
@@ -1535,7 +1537,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
`,
`
// Initialize test accounts
@@ -1543,7 +1545,7 @@ var bindTests = []struct {
addr := crypto.PubkeyToAddress(key.PublicKey)
// Deploy registrar contract
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -1598,14 +1600,14 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
`,
`
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
// Deploy registrar contract
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -1659,7 +1661,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
@@ -1667,7 +1669,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
defer sim.Close()
// Deploy a tester contract and execute a structured call on it
@@ -1720,14 +1722,14 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
`,
`
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
- sim := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 1000000)
+ sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 1000000)
defer sim.Close()
opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -1808,7 +1810,7 @@ var bindTests = []struct {
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
`,
@@ -1816,7 +1818,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
+ sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
)
defer sim.Close()
@@ -1874,11 +1876,12 @@ var bindTests = []struct {
[]string{"0x6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063726c638214602d575b600080fd5b60336035565b005b60405163024876cd60e61b815260016004820152600260248201526003604482015260640160405180910390fdfea264697066735822122093f786a1bc60216540cd999fbb4a6109e0fef20abcff6e9107fb2817ca968f3c64736f6c63430008070033"},
[]string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"},{"inputs":[],"name":"Error","outputs":[],"stateMutability":"pure","type":"function"}]`},
`
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
`,
@@ -1886,7 +1889,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
+ sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
)
defer sim.Close()
@@ -1895,7 +1898,7 @@ var bindTests = []struct {
t.Fatal(err)
}
sim.Commit()
- _, err = bind.WaitDeployed(nil, sim, tx)
+ _, err = bind.WaitDeployed(context.Background(), sim, tx)
if err != nil {
t.Error(err)
}
@@ -1926,11 +1929,12 @@ var bindTests = []struct {
bytecode: []string{`0x608060405234801561001057600080fd5b506040516101c43803806101c48339818101604052810190610032919061014a565b50610177565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100958261004c565b810181811067ffffffffffffffff821117156100b4576100b361005d565b5b80604052505050565b60006100c7610038565b90506100d3828261008c565b919050565b6000819050919050565b6100eb816100d8565b81146100f657600080fd5b50565b600081519050610108816100e2565b92915050565b60006020828403121561012457610123610047565b5b61012e60206100bd565b9050600061013e848285016100f9565b60008301525092915050565b6000602082840312156101605761015f610042565b5b600061016e8482850161010e565b91505092915050565b603f806101856000396000f3fe6080604052600080fdfea2646970667358221220cdffa667affecefac5561f65f4a4ba914204a8d4eb859d8cd426fb306e5c12a364736f6c634300080a0033`},
abi: []string{`[{"inputs":[{"components":[{"internalType":"uint256","name":"field","type":"uint256"}],"internalType":"struct ConstructorWithStructParam.StructType","name":"st","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"}]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
`,
@@ -1938,7 +1942,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
+ sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
)
defer sim.Close()
@@ -1948,7 +1952,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Logf("Deployment tx: %+v", tx)
t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err)
}
@@ -1974,11 +1978,12 @@ var bindTests = []struct {
bytecode: []string{"0x608060405234801561001057600080fd5b5061042b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063c2bb515f1461003b578063cce7b04814610059575b600080fd5b610043610075565b60405161005091906101af565b60405180910390f35b610073600480360381019061006e91906103ac565b6100b5565b005b61007d6100b8565b604051806040016040528060405180602001604052806000815250815260200160405180602001604052806000815250815250905090565b50565b604051806040016040528060608152602001606081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561010c5780820151818401526020810190506100f1565b8381111561011b576000848401525b50505050565b6000601f19601f8301169050919050565b600061013d826100d2565b61014781856100dd565b93506101578185602086016100ee565b61016081610121565b840191505092915050565b600060408301600083015184820360008601526101888282610132565b915050602083015184820360208601526101a28282610132565b9150508091505092915050565b600060208201905081810360008301526101c9818461016b565b905092915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61022282610121565b810181811067ffffffffffffffff82111715610241576102406101ea565b5b80604052505050565b60006102546101d1565b90506102608282610219565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561028f5761028e6101ea565b5b61029882610121565b9050602081019050919050565b82818337600083830152505050565b60006102c76102c284610274565b61024a565b9050828152602081018484840111156102e3576102e261026f565b5b6102ee8482856102a5565b509392505050565b600082601f83011261030b5761030a61026a565b5b813561031b8482602086016102b4565b91505092915050565b60006040828403121561033a576103396101e5565b5b610344604061024a565b9050600082013567ffffffffffffffff81111561036457610363610265565b5b610370848285016102f6565b600083015250602082013567ffffffffffffffff81111561039457610393610265565b5b6103a0848285016102f6565b60208301525092915050565b6000602082840312156103c2576103c16101db565b5b600082013567ffffffffffffffff8111156103e0576103df6101e0565b5b6103ec84828501610324565b9150509291505056fea264697066735822122033bca1606af9b6aeba1673f98c52003cec19338539fb44b86690ce82c51483b564736f6c634300080e0033"},
abi: []string{`[ { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "int256", "name": "msg", "type": "int256" }, { "indexed": false, "internalType": "int256", "name": "_msg", "type": "int256" } ], "name": "log", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "req", "type": "tuple" } ], "name": "addRequest", "outputs": [], "stateMutability": "pure", "type": "function" }, { "inputs": [], "name": "getRequest", "outputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "", "type": "tuple" } ], "stateMutability": "pure", "type": "function" } ]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
`,
@@ -1986,7 +1991,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
+ sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
)
defer sim.Close()
@@ -1996,7 +2001,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Logf("Deployment tx: %+v", tx)
t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err)
}
@@ -2014,11 +2019,12 @@ var bindTests = []struct {
bytecode: []string{"0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063527a119f14602d575b600080fd5b60436004803603810190603f9190605b565b6045565b005b50565b6000813590506055816092565b92915050565b600060208284031215606e57606d608d565b5b6000607a848285016048565b91505092915050565b6000819050919050565b600080fd5b6099816083565b811460a357600080fd5b5056fea2646970667358221220d4f4525e2615516394055d369fb17df41c359e5e962734f27fd683ea81fd9db164736f6c63430008070033"},
abi: []string{`[{"inputs":[{"internalType":"uint256","name":"range","type":"uint256"}],"name":"functionWithKeywordParameter","outputs":[],"stateMutability":"pure","type":"function"}]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
`,
@@ -2026,7 +2032,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
+ sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
)
_, tx, _, err := DeployRangeKeyword(user, sim)
if err != nil {
@@ -2034,7 +2040,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Errorf("error deploying the contract: %v", err)
}
`,
diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go
index 5af2a8acbb..7541685460 100644
--- a/accounts/abi/bind/util_test.go
+++ b/accounts/abi/bind/util_test.go
@@ -24,11 +24,10 @@ import (
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/ethereum/go-ethereum/params"
)
@@ -56,20 +55,19 @@ var waitDeployedTests = map[string]struct {
func TestWaitDeployed(t *testing.T) {
t.Parallel()
for name, test := range waitDeployedTests {
- backend := backends.NewSimulatedBackend(
- core.GenesisAlloc{
+ backend := simulated.NewBackend(
+ types.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
- 10000000,
)
defer backend.Close()
// Create the transaction
- head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey)
// Wait for it to get mined in the background.
var (
@@ -80,13 +78,13 @@ func TestWaitDeployed(t *testing.T) {
)
go func() {
- address, err = bind.WaitDeployed(ctx, backend, tx)
+ address, err = bind.WaitDeployed(ctx, backend.Client(), tx)
close(mined)
}()
// Send and mine the transaction.
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
backend.Commit()
select {
@@ -105,43 +103,41 @@ func TestWaitDeployed(t *testing.T) {
}
func TestWaitDeployedCornerCases(t *testing.T) {
- t.Parallel()
- backend := backends.NewSimulatedBackend(
- core.GenesisAlloc{
+ backend := simulated.NewBackend(
+ types.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
- 10000000,
)
defer backend.Close()
- head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
// Create a transaction to an account.
code := "6060604052600a8060106000396000f360606040526008565b00"
tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
backend.Commit()
notContractCreation := errors.New("tx is not contract creation")
- if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContractCreation.Error() {
+ if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() {
t.Errorf("error mismatch: want %q, got %q, ", notContractCreation, err)
}
// Create a transaction that is not mined.
tx = types.NewContractCreation(1, big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
go func() {
contextCanceled := errors.New("context canceled")
- if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != contextCanceled.Error() {
+ if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != contextCanceled.Error() {
t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
}
}()
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
cancel()
}
diff --git a/accounts/abi/topics.go b/accounts/abi/topics.go
index 0313d831c3..3286c8ebba 100644
--- a/accounts/abi/topics.go
+++ b/accounts/abi/topics.go
@@ -24,6 +24,7 @@ import (
"reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -42,8 +43,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
case common.Address:
copy(topic[common.HashLength-common.AddressLength:], rule[:])
case *big.Int:
- blob := rule.Bytes()
- copy(topic[common.HashLength-len(blob):], blob)
+ copy(topic[:], math.U256Bytes(rule))
case bool:
if rule {
topic[common.HashLength-1] = 1
diff --git a/accounts/abi/topics_test.go b/accounts/abi/topics_test.go
index 1b0aaa2a39..1bf9e3c60b 100644
--- a/accounts/abi/topics_test.go
+++ b/accounts/abi/topics_test.go
@@ -17,6 +17,7 @@
package abi
import (
+ "math"
"math/big"
"reflect"
"testing"
@@ -56,9 +57,27 @@ func TestMakeTopics(t *testing.T) {
false,
},
{
- "support *big.Int types in topics",
- args{[][]interface{}{{big.NewInt(1).Lsh(big.NewInt(2), 254)}}},
- [][]common.Hash{{common.Hash{128}}},
+ "support positive *big.Int types in topics",
+ args{[][]interface{}{
+ {big.NewInt(1)},
+ {big.NewInt(1).Lsh(big.NewInt(2), 254)},
+ }},
+ [][]common.Hash{
+ {common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001")},
+ {common.Hash{128}},
+ },
+ false,
+ },
+ {
+ "support negative *big.Int types in topics",
+ args{[][]interface{}{
+ {big.NewInt(-1)},
+ {big.NewInt(math.MinInt64)},
+ }},
+ [][]common.Hash{
+ {common.MaxHash},
+ {common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")},
+ },
false,
},
{
diff --git a/accounts/keystore/passphrase.go b/accounts/keystore/passphrase.go
index 55aaf1b204..fad6ef04e4 100644
--- a/accounts/keystore/passphrase.go
+++ b/accounts/keystore/passphrase.go
@@ -141,7 +141,7 @@ func (ks keyStorePassphrase) JoinPath(filename string) string {
return filepath.Join(ks.keysDirPath, filename)
}
-// Encryptdata encrypts the data given as 'data' with the password 'auth'.
+// EncryptDataV3 encrypts the data given as 'data' with the password 'auth'.
func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error) {
salt := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
diff --git a/accounts/manager.go b/accounts/manager.go
index d04593b3ce..e3c0637035 100644
--- a/accounts/manager.go
+++ b/accounts/manager.go
@@ -100,6 +100,9 @@ func NewManager(config *Config, backends ...Backend) *Manager {
// Close terminates the account manager's internal notification processes.
func (am *Manager) Close() error {
+ for _, w := range am.wallets {
+ w.Close()
+ }
errc := make(chan error)
am.quit <- errc
diff --git a/accounts/scwallet/hub.go b/accounts/scwallet/hub.go
index c01959371b..33307bb043 100644
--- a/accounts/scwallet/hub.go
+++ b/accounts/scwallet/hub.go
@@ -256,7 +256,7 @@ func (hub *Hub) refreshWallets() {
continue
}
- // Card connected, start tracking in amongst the wallets
+ // Card connected, start tracking among the wallets
hub.wallets[reader] = wallet
events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
}
diff --git a/accounts/usbwallet/trezor/trezor.go b/accounts/usbwallet/trezor/trezor.go
index 6f75129704..107b5db912 100644
--- a/accounts/usbwallet/trezor/trezor.go
+++ b/accounts/usbwallet/trezor/trezor.go
@@ -16,7 +16,7 @@
// This file contains the implementation for interacting with the Trezor hardware
// wallets. The wire protocol spec can be found on the SatoshiLabs website:
-// https://wiki.trezor.io/Developers_guide-Message_Workflows
+// https://docs.trezor.io/trezor-firmware/common/message-workflows.html
// !!! STAHP !!!
//
diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go
index b7117c9b1b..12709207df 100644
--- a/accounts/usbwallet/wallet.go
+++ b/accounts/usbwallet/wallet.go
@@ -505,6 +505,10 @@ func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
w.stateLock.Lock()
defer w.stateLock.Unlock()
+ if w.device == nil {
+ return accounts.Account{}, accounts.ErrWalletClosed
+ }
+
if _, ok := w.paths[address]; !ok {
w.accounts = append(w.accounts, account)
w.paths[address] = make(accounts.DerivationPath, len(path))
diff --git a/beacon/engine/types.go b/beacon/engine/types.go
index 356ac3200c..ecd870847f 100644
--- a/beacon/engine/types.go
+++ b/beacon/engine/types.go
@@ -26,6 +26,16 @@ import (
"github.com/ethereum/go-ethereum/trie"
)
+// PayloadVersion denotes the version of PayloadAttributes used to request the
+// building of the payload to commence.
+type PayloadVersion byte
+
+var (
+ PayloadV1 PayloadVersion = 0x1
+ PayloadV2 PayloadVersion = 0x2
+ PayloadV3 PayloadVersion = 0x3
+)
+
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
// PayloadAttributes describes the environment context in which a block should
@@ -115,6 +125,21 @@ type TransitionConfigurationV1 struct {
// PayloadID is an identifier of the payload build process
type PayloadID [8]byte
+// Version returns the payload version associated with the identifier.
+func (b PayloadID) Version() PayloadVersion {
+ return PayloadVersion(b[0])
+}
+
+// Is returns whether the identifier matches any of provided payload versions.
+func (b PayloadID) Is(versions ...PayloadVersion) bool {
+ for _, v := range versions {
+ if v == b.Version() {
+ return true
+ }
+ }
+ return false
+}
+
func (b PayloadID) String() string {
return hexutil.Encode(b[:])
}
@@ -289,3 +314,21 @@ type ExecutionPayloadBodyV1 struct {
TransactionData []hexutil.Bytes `json:"transactions"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
}
+
+// Client identifiers to support ClientVersionV1.
+const (
+ ClientCode = "GE"
+ ClientName = "go-ethereum"
+)
+
+// ClientVersionV1 contains information which identifies a client implementation.
+type ClientVersionV1 struct {
+ Code string `json:"code"`
+ Name string `json:"clientName"`
+ Version string `json:"version"`
+ Commit string `json:"commit"`
+}
+
+func (v *ClientVersionV1) String() string {
+ return fmt.Sprintf("%s-%s-%s-%s", v.Code, v.Name, v.Version, v.Commit)
+}
diff --git a/build/checksums.txt b/build/checksums.txt
index 893f31587d..f92f739a2f 100644
--- a/build/checksums.txt
+++ b/build/checksums.txt
@@ -1,9 +1,9 @@
# This file contains sha256 checksums of optional build dependencies.
-# version:spec-tests 1.0.6
+# version:spec-tests 2.1.0
# https://github.com/ethereum/execution-spec-tests/releases
-# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.6/
-485af7b66cf41eb3a8c1bd46632913b8eb95995df867cf665617bbc9b4beedd1 fixtures_develop.tar.gz
+# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
+ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
# version:golang 1.22.1
# https://go.dev/dl/
@@ -22,35 +22,36 @@ ac775e19d93cc1668999b77cfe8c8964abfbc658718feccfe6e0eb87663cd668 go1.22.1.linux
cf9c66a208a106402a527f5b956269ca506cfe535fc388e828d249ea88ed28ba go1.22.1.windows-amd64.zip
85b8511b298c9f4199ecae26afafcc3d46155bac934d43f2357b9224bcaa310f go1.22.1.windows-arm64.zip
-# version:golangci 1.51.1
+# version:golangci 1.55.2
# https://github.com/golangci/golangci-lint/releases/
-# https://github.com/golangci/golangci-lint/releases/download/v1.51.1/
-fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz
-75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz
-e06b3459aaed356e1667580be00b05f41f3b2e29685d12cdee571c23e1edb414 golangci-lint-1.51.1-freebsd-386.tar.gz
-623ce2d0fa4d35cc2e8d69fa7334227ab592380962a13b4d9cdc77cf41db2008 golangci-lint-1.51.1-freebsd-amd64.tar.gz
-131365feb0584cc2736c43192fa673ca50e5b6b765456990cb379ecfb787e568 golangci-lint-1.51.1-freebsd-armv6.tar.gz
-98fb627927cbb654f5bf85dcffc5f646666b2ce96ea0fed977c9fb28abd51532 golangci-lint-1.51.1-freebsd-armv7.tar.gz
-b36a99702fa762c15840261bc0fb41b4b1b16b8b19b8c0941bae98c85bb0f8b8 golangci-lint-1.51.1-linux-386.tar.gz
-17aeb26c76820c22efa0e1838b0ab93e90cfedef43fbfc9a2f33f27eb9e5e070 golangci-lint-1.51.1-linux-amd64.tar.gz
-9744bc34e7b8d82ca788b667bfb7155a39b4be9aef43bf9f10318b1372cea338 golangci-lint-1.51.1-linux-arm64.tar.gz
-0dda8dbeb2ff7455a044ec8e347f2fc6d655d2e99d281b3b95e88167031c673d golangci-lint-1.51.1-linux-armv6.tar.gz
-0512f311b11d43b8b22989d929f0fe8a2e1e5ebe497f1eb0ff73a0fc3d188fd1 golangci-lint-1.51.1-linux-armv7.tar.gz
-d767108dcf84a8eaa844df3454cb0f75a492f4e7102ecc2b0a3545cfe073a566 golangci-lint-1.51.1-linux-loong64.tar.gz
-3bd56c54daec16585b2668e0dfabb27af2c2b38cc0fdb46923e2521e1634846b golangci-lint-1.51.1-linux-mips64.tar.gz
-f72f5adfa2219e15d2414c9a2966f86e74556cf17a85c727a7fb7770a16cf814 golangci-lint-1.51.1-linux-mips64le.tar.gz
-e605521dac98096d8737e1997c954f41f1d0d8275b8731f62783d410c23574b9 golangci-lint-1.51.1-linux-ppc64le.tar.gz
-2f683217b814339e74d61ca700922d8407f15addd6d4c5e8b156fbab79f26a87 golangci-lint-1.51.1-linux-riscv64.tar.gz
-d98528292b65971a3594e5880530e7624597dc9806fcfccdfbe39be411713d63 golangci-lint-1.51.1-linux-s390x.tar.gz
-9bb2d0fe9e692ed0aea4f2537e3e6862b2f6768fe2849a84f4a6ad09da9fd971 golangci-lint-1.51.1-netbsd-386.tar.gz
-34cafdcd11ae73ae88d66c33eb8449f5c976fc3e37b44774dbe9c71caa95e592 golangci-lint-1.51.1-netbsd-amd64.tar.gz
-f8b4e1e47ac17caafe8a5f32f975a2b6a7cb14c27c0f73c1fb15c20ca91c2e03 golangci-lint-1.51.1-netbsd-armv6.tar.gz
-c4f58b7e227b9fd41f0e9310dc83f4a4e7d026598e2f6e95b78761081a6d9bd2 golangci-lint-1.51.1-netbsd-armv7.tar.gz
-6710e2f5375dc75521c1a17980a6cbbe6ff76c2f8b852964a8af558899a97cf5 golangci-lint-1.51.1-windows-386.zip
-722d7b87b9cdda0a3835d5030b3fc5385c2eba4c107f63f6391cfb2ac35f051d golangci-lint-1.51.1-windows-amd64.zip
-eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip
-bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip
-cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip
+# https://github.com/golangci/golangci-lint/releases/download/v1.55.2/
+632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz
+234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz
+2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz
+e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz
+5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz
+7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz
+33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz
+57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz
+ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz
+8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz
+3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz
+c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz
+758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz
+2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz
+024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz
+6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz
+0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz
+30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz
+5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz
+95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz
+94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz
+ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz
+45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip
+f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip
+fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip
+1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip
+a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
#
diff --git a/build/ci.go b/build/ci.go
index d72aed775f..68d11b88e6 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -121,14 +121,14 @@ var (
// Note: vivid is unsupported because there is no golang-1.6 package for it.
// Note: the following Ubuntu releases have been officially deprecated on Launchpad:
// wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish,
- // kinetic
+ // kinetic, lunar
debDistroGoBoots = map[string]string{
- "trusty": "golang-1.11", // EOL: 04/2024
- "xenial": "golang-go", // EOL: 04/2026
- "bionic": "golang-go", // EOL: 04/2028
- "focal": "golang-go", // EOL: 04/2030
- "jammy": "golang-go", // EOL: 04/2032
- "lunar": "golang-go", // EOL: 01/2024
+ "trusty": "golang-1.11", // 14.04, EOL: 04/2024
+ "xenial": "golang-go", // 16.04, EOL: 04/2026
+ "bionic": "golang-go", // 18.04, EOL: 04/2028
+ "focal": "golang-go", // 20.04, EOL: 04/2030
+ "jammy": "golang-go", // 22.04, EOL: 04/2032
+ "mantic": "golang-go", // 23.10, EOL: 07/2024
}
debGoBootPaths = map[string]string{
@@ -366,7 +366,7 @@ func doLint(cmdline []string) {
linter := downloadLinter(*cachedir)
lflags := []string{"run", "--config", ".golangci.yml"}
- build.MustRunCommand(linter, append(lflags, packages...)...)
+ build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
fmt.Println("You have achieved perfection.")
}
diff --git a/cmd/clef/README.md b/cmd/clef/README.md
index 3a43db8c95..cf09265136 100644
--- a/cmd/clef/README.md
+++ b/cmd/clef/README.md
@@ -916,7 +916,7 @@ There are a couple of implementation for a UI. We'll try to keep this list up to
| Name | Repo | UI type| No external resources| Blocky support| Verifies permissions | Hash information | No secondary storage | Statically linked| Can modify parameters|
| ---- | ---- | -------| ---- | ---- | ---- |---- | ---- | ---- | ---- |
-| QtSigner| https://github.com/holiman/qtsigner/| Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)|
-| GtkSigner| https://github.com/holiman/gtksigner| Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: |
-| Frame | https://github.com/floating/frame/commits/go-signer| Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: |
-| Clef UI| https://github.com/ethereum/clef-ui| Golang/QT-based| :+1:| :+1:| :x:| :+1:| :+1:| :x: | :+1: (approve tx only)|
+| QtSigner| https://github.com/holiman/qtsigner/ | Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)|
+| GtkSigner| https://github.com/holiman/gtksigner | Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: |
+| Frame | https://github.com/floating/frame/commits/go-signer | Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: |
+| Clef UI| https://github.com/ethereum/clef-ui | Golang/QT-based| :+1:| :+1:| :x:| :+1:| :+1:| :x: | :+1: (approve tx only)|
diff --git a/cmd/clef/main.go b/cmd/clef/main.go
index f9738491b2..e1480c68e9 100644
--- a/cmd/clef/main.go
+++ b/cmd/clef/main.go
@@ -784,6 +784,7 @@ func signer(c *cli.Context) error {
"light-kdf", lightKdf, "advanced", advanced)
am := core.StartClefAccountManager(ksLoc, nousb, lightKdf, scpath)
+ defer am.Close()
apiImpl := core.NewSignerAPI(am, chainId, nousb, ui, db, advanced, pwStorage)
// Establish the bidirectional communication, by creating a new UI backend and registering
@@ -817,7 +818,7 @@ func signer(c *cli.Context) error {
vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.Name))
cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name))
- srv := rpc.NewServer("", 0, 0)
+ srv := rpc.NewServer()
srv.SetBatchLimits(node.DefaultConfig.BatchRequestLimit, node.DefaultConfig.BatchResponseMaxSize)
err := node.RegisterApis(rpcAPI, []string{"account"}, srv)
if err != nil {
diff --git a/cmd/devp2p/README.md b/cmd/devp2p/README.md
index 5ca7b497a2..284dfe0a45 100644
--- a/cmd/devp2p/README.md
+++ b/cmd/devp2p/README.md
@@ -108,31 +108,32 @@ Start the test by running `devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.
The Eth Protocol test suite is a conformance test suite for the [eth protocol][eth].
-To run the eth protocol test suite against your implementation, the node needs to be initialized as such:
+To run the eth protocol test suite against your implementation, the node needs to be initialized
+with our test chain. The chain files are located in `./cmd/devp2p/internal/ethtest/testdata`.
-1. initialize the geth node with the `genesis.json` file contained in the `testdata` directory
-2. import the `halfchain.rlp` file in the `testdata` directory
-3. run geth with the following flags:
-```
-geth --datadir --nodiscover --nat=none --networkid 19763 --verbosity 5
-```
+1. initialize the geth node with the `genesis.json` file
+2. import blocks from `chain.rlp`
+3. run the client using the resulting database. For geth, use a command like the one below:
-Then, run the following command, replacing `` with the enode of the geth node:
- ```
- devp2p rlpx eth-test cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
-```
+ geth \
+ --datadir \
+ --nodiscover \
+ --nat=none \
+ --networkid 3503995874084926 \
+ --verbosity 5 \
+ --authrpc.jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
+
+Note that the tests also require access to the engine API.
+The test suite can now be executed using the devp2p tool.
+
+ devp2p rlpx eth-test \
+ --chain internal/ethtest/testdata \
+ --node enode://.... \
+ --engineapi http://127.0.0.1:8551 \
+ --jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
Repeat the above process (re-initialising the node) in order to run the Eth Protocol test suite again.
-#### Eth66 Test Suite
-
-The Eth66 test suite is also a conformance test suite for the eth 66 protocol version specifically.
-To run the eth66 protocol test suite, initialize a geth node as described above and run the following command,
-replacing `` with the enode of the geth node:
-
- ```
- devp2p rlpx eth66-test cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
-```
[eth]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md
[dns-tutorial]: https://geth.ethereum.org/docs/developers/geth-developer/dns-discovery-setup
diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go
index 007b442ec3..b431260595 100644
--- a/cmd/devp2p/discv4cmd.go
+++ b/cmd/devp2p/discv4cmd.go
@@ -188,7 +188,7 @@ func discv4Listen(ctx *cli.Context) error {
api := &discv4API{disc}
log.Info("Starting RPC API server", "addr", httpAddr)
- srv := rpc.NewServer("", 0, 0)
+ srv := rpc.NewServer()
srv.RegisterName("discv4", api)
http.DefaultServeMux.Handle("/", srv)
httpsrv := http.Server{Addr: httpAddr, Handler: http.DefaultServeMux}
diff --git a/cmd/devp2p/internal/ethtest/chain.go b/cmd/devp2p/internal/ethtest/chain.go
index a1b9220f4b..d11c20462e 100644
--- a/cmd/devp2p/internal/ethtest/chain.go
+++ b/cmd/devp2p/internal/ethtest/chain.go
@@ -17,27 +17,118 @@
package ethtest
import (
+ "bytes"
"compress/gzip"
+ "crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"os"
+ "path"
+ "sort"
"strings"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
+ "golang.org/x/exp/slices"
)
+// Chain is a lightweight blockchain-like store which can read a hivechain
+// created chain.
type Chain struct {
- genesis core.Genesis
- blocks []*types.Block
- chainConfig *params.ChainConfig
+ genesis core.Genesis
+ blocks []*types.Block
+ state map[common.Address]state.DumpAccount // state of head block
+ senders map[common.Address]*senderInfo
+ config *params.ChainConfig
+}
+
+// NewChain takes the given chain.rlp file, and decodes and returns
+// the blocks from the file.
+func NewChain(dir string) (*Chain, error) {
+ gen, err := loadGenesis(path.Join(dir, "genesis.json"))
+ if err != nil {
+ return nil, err
+ }
+ gblock := gen.ToBlock()
+
+ blocks, err := blocksFromFile(path.Join(dir, "chain.rlp"), gblock)
+ if err != nil {
+ return nil, err
+ }
+ state, err := readState(path.Join(dir, "headstate.json"))
+ if err != nil {
+ return nil, err
+ }
+ accounts, err := readAccounts(path.Join(dir, "accounts.json"))
+ if err != nil {
+ return nil, err
+ }
+ return &Chain{
+ genesis: gen,
+ blocks: blocks,
+ state: state,
+ senders: accounts,
+ config: gen.Config,
+ }, nil
+}
+
+// senderInfo is an account record as output in the "accounts.json" file from
+// hivechain.
+type senderInfo struct {
+ Key *ecdsa.PrivateKey `json:"key"`
+ Nonce uint64 `json:"nonce"`
+}
+
+// Head returns the chain head.
+func (c *Chain) Head() *types.Block {
+ return c.blocks[c.Len()-1]
+}
+
+// AccountsInHashOrder returns all accounts of the head state, ordered by hash of address.
+func (c *Chain) AccountsInHashOrder() []state.DumpAccount {
+ list := make([]state.DumpAccount, len(c.state))
+ i := 0
+ for addr, acc := range c.state {
+ addr := addr
+ list[i] = acc
+ list[i].Address = &addr
+ if len(acc.AddressHash) != 32 {
+ panic(fmt.Errorf("missing/invalid SecureKey in dump account %v", addr))
+ }
+ i++
+ }
+ slices.SortFunc(list, func(x, y state.DumpAccount) int {
+ return bytes.Compare(x.AddressHash, y.AddressHash)
+ })
+ return list
+}
+
+// CodeHashes returns all bytecode hashes contained in the head state.
+func (c *Chain) CodeHashes() []common.Hash {
+ var hashes []common.Hash
+ seen := make(map[common.Hash]struct{})
+ seen[types.EmptyCodeHash] = struct{}{}
+ for _, acc := range c.state {
+ h := common.BytesToHash(acc.CodeHash)
+ if _, ok := seen[h]; ok {
+ continue
+ }
+ hashes = append(hashes, h)
+ seen[h] = struct{}{}
+ }
+ slices.SortFunc(hashes, (common.Hash).Cmp)
+ return hashes
}
// Len returns the length of the chain.
@@ -45,6 +136,11 @@ func (c *Chain) Len() int {
return len(c.blocks)
}
+// ForkID gets the fork id of the chain.
+func (c *Chain) ForkID() forkid.ID {
+ return forkid.NewID(c.config, c.blocks[0], uint64(c.Len()), c.blocks[c.Len()-1].Time())
+}
+
// TD calculates the total difficulty of the chain at the
// chain head.
func (c *Chain) TD() *big.Int {
@@ -56,63 +152,71 @@ func (c *Chain) TD() *big.Int {
return sum
}
-// TotalDifficultyAt calculates the total difficulty of the chain
-// at the given block height.
-func (c *Chain) TotalDifficultyAt(height int) *big.Int {
- sum := new(big.Int)
- if height >= c.Len() {
- return sum
- }
-
- for _, block := range c.blocks[:height+1] {
- sum.Add(sum, block.Difficulty())
- }
-
- return sum
+// GetBlock returns the block at the specified number.
+func (c *Chain) GetBlock(number int) *types.Block {
+ return c.blocks[number]
}
+// RootAt returns the state root for the block at the given height.
func (c *Chain) RootAt(height int) common.Hash {
if height < c.Len() {
return c.blocks[height].Root()
}
-
return common.Hash{}
}
-// ForkID gets the fork id of the chain.
-func (c *Chain) ForkID() forkid.ID {
- return forkid.NewID(c.chainConfig, c.blocks[0], uint64(c.Len()), c.blocks[0].Time())
-}
-
-// Shorten returns a copy chain of a desired height from the imported
-func (c *Chain) Shorten(height int) *Chain {
- blocks := make([]*types.Block, height)
- copy(blocks, c.blocks[:height])
-
- config := *c.chainConfig
-
- return &Chain{
- blocks: blocks,
- chainConfig: &config,
+// GetSender returns the address associated with account at the index in the
+// pre-funded accounts list.
+func (c *Chain) GetSender(idx int) (common.Address, uint64) {
+ var accounts Addresses
+ for addr := range c.senders {
+ accounts = append(accounts, addr)
}
+ sort.Sort(accounts)
+ addr := accounts[idx]
+ return addr, c.senders[addr].Nonce
}
-// Head returns the chain head.
-func (c *Chain) Head() *types.Block {
- return c.blocks[c.Len()-1]
+// IncNonce increases the specified signing account's pending nonce.
+func (c *Chain) IncNonce(addr common.Address, amt uint64) {
+ if _, ok := c.senders[addr]; !ok {
+ panic("nonce increment for non-signer")
+ }
+ c.senders[addr].Nonce += amt
}
-// nolint:typecheck
-func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
+// Balance returns the balance of an account at the head of the chain.
+func (c *Chain) Balance(addr common.Address) *big.Int {
+ bal := new(big.Int)
+ if acc, ok := c.state[addr]; ok {
+ bal, _ = bal.SetString(acc.Balance, 10)
+ }
+ return bal
+}
+
+// SignTx signs a transaction for the specified from account, so long as that
+// account was in the hivechain accounts dump.
+func (c *Chain) SignTx(from common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ signer := types.LatestSigner(c.config)
+ acc, ok := c.senders[from]
+ if !ok {
+ return nil, fmt.Errorf("account not available for signing: %s", from)
+ }
+
+ return types.SignTx(tx, signer, acc.Key)
+}
+
+// GetHeaders returns the headers base on an ethGetPacketHeadersPacket.
+func (c *Chain) GetHeaders(req *eth.GetBlockHeadersPacket) ([]*types.Header, error) {
if req.Amount < 1 {
return nil, errors.New("no block headers requested")
}
+ var (
+ headers = make([]*types.Header, req.Amount)
+ blockNumber uint64
+ )
- headers := make([]*types.Header, req.Amount)
-
- var blockNumber uint64
-
- // range over blocks to check if our chain has the requested header
+ // Range over blocks to check if our chain has the requested header.
for _, block := range c.blocks {
if block.Hash() == req.Origin.Hash || block.Number().Uint64() == req.Origin.Number {
headers[0] = block.Header()
@@ -123,42 +227,31 @@ func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
if headers[0] == nil {
return nil, fmt.Errorf("no headers found for given origin number %v, hash %v", req.Origin.Number, req.Origin.Hash)
}
-
if req.Reverse {
for i := 1; i < int(req.Amount); i++ {
blockNumber -= (1 - req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
-
return headers, nil
}
-
for i := 1; i < int(req.Amount); i++ {
blockNumber += (1 + req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
-
return headers, nil
}
-// loadChain takes the given chain.rlp file, and decodes and returns
-// the blocks from the file.
-func loadChain(chainfile string, genesis string) (*Chain, error) {
- gen, err := loadGenesis(genesis)
- if err != nil {
- return nil, err
+// Shorten returns a copy chain of a desired height from the imported
+func (c *Chain) Shorten(height int) *Chain {
+ blocks := make([]*types.Block, height)
+ copy(blocks, c.blocks[:height])
+
+ config := *c.config
+
+ return &Chain{
+ blocks: blocks,
+ config: &config,
}
-
- gblock := gen.ToBlock()
-
- blocks, err := blocksFromFile(chainfile, gblock)
- if err != nil {
- return nil, err
- }
-
- c := &Chain{genesis: gen, blocks: blocks, chainConfig: gen.Config}
-
- return c, nil
}
func loadGenesis(genesisFile string) (core.Genesis, error) {
@@ -175,6 +268,22 @@ func loadGenesis(genesisFile string) (core.Genesis, error) {
return gen, nil
}
+type Addresses []common.Address
+
+func (a Addresses) Len() int {
+ return len(a)
+}
+
+func (a Addresses) Less(i, j int) bool {
+ return bytes.Compare(a[i][:], a[j][:]) < 0
+}
+
+func (a Addresses) Swap(i, j int) {
+ tmp := a[i]
+ a[i] = a[j]
+ a[j] = tmp
+}
+
func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) {
// Load chain.rlp.
fh, err := os.Open(chainfile)
@@ -213,3 +322,47 @@ func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, erro
return blocks, nil
}
+
+func readState(file string) (map[common.Address]state.DumpAccount, error) {
+ f, err := os.ReadFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read state: %v", err)
+ }
+ var dump state.Dump
+ if err := json.Unmarshal(f, &dump); err != nil {
+ return nil, fmt.Errorf("unable to unmarshal state: %v", err)
+ }
+
+ state := make(map[common.Address]state.DumpAccount)
+ for key, acct := range dump.Accounts {
+ var addr common.Address
+ if err := addr.UnmarshalText([]byte(key)); err != nil {
+ return nil, fmt.Errorf("invalid address %q", key)
+ }
+ state[addr] = acct
+ }
+ return state, nil
+}
+
+func readAccounts(file string) (map[common.Address]*senderInfo, error) {
+ f, err := os.ReadFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read state: %v", err)
+ }
+ type account struct {
+ Key hexutil.Bytes `json:"key"`
+ }
+ keys := make(map[common.Address]account)
+ if err := json.Unmarshal(f, &keys); err != nil {
+ return nil, fmt.Errorf("unable to unmarshal accounts: %v", err)
+ }
+ accounts := make(map[common.Address]*senderInfo)
+ for addr, acc := range keys {
+ pk, err := crypto.HexToECDSA(common.Bytes2Hex(acc.Key))
+ if err != nil {
+ return nil, fmt.Errorf("unable to read private key for %s: %v", err, addr)
+ }
+ accounts[addr] = &senderInfo{Key: pk, Nonce: 0}
+ }
+ return accounts, nil
+}
diff --git a/cmd/devp2p/internal/ethtest/chain_test.go b/cmd/devp2p/internal/ethtest/chain_test.go
index 04da591cb8..2d40b04b1b 100644
--- a/cmd/devp2p/internal/ethtest/chain_test.go
+++ b/cmd/devp2p/internal/ethtest/chain_test.go
@@ -123,31 +123,26 @@ func TestEthProtocolNegotiation(t *testing.T) {
}
}
-// TestChain_GetHeaders tests whether the test suite can correctly
+// TestChainGetHeaders tests whether the test suite can correctly
// respond to a GetBlockHeaders request from a node.
-func TestChain_GetHeaders(t *testing.T) {
+func TestChainGetHeaders(t *testing.T) {
t.Parallel()
- chainFile, err := filepath.Abs("./testdata/chain.rlp")
+
+ dir, err := filepath.Abs("./testdata")
if err != nil {
t.Fatal(err)
}
-
- genesisFile, err := filepath.Abs("./testdata/genesis.json")
- if err != nil {
- t.Fatal(err)
- }
-
- chain, err := loadChain(chainFile, genesisFile)
+ chain, err := NewChain(dir)
if err != nil {
t.Fatal(err)
}
var tests = []struct {
- req GetBlockHeaders
+ req eth.GetBlockHeadersPacket
expected []*types.Header
}{
{
- req: GetBlockHeaders{
+ req: eth.GetBlockHeadersPacket{
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: uint64(2)},
Amount: uint64(5),
@@ -164,7 +159,7 @@ func TestChain_GetHeaders(t *testing.T) {
},
},
{
- req: GetBlockHeaders{
+ req: eth.GetBlockHeadersPacket{
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
Amount: uint64(3),
@@ -179,7 +174,7 @@ func TestChain_GetHeaders(t *testing.T) {
},
},
{
- req: GetBlockHeaders{
+ req: eth.GetBlockHeadersPacket{
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
Amount: uint64(1),
diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go
new file mode 100644
index 0000000000..ba3c0585fd
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/conn.go
@@ -0,0 +1,361 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package ethtest
+
+import (
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "net"
+ "reflect"
+ "time"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
+ "github.com/ethereum/go-ethereum/eth/protocols/snap"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/rlpx"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+var (
+ pretty = spew.ConfigState{
+ Indent: " ",
+ DisableCapacities: true,
+ DisablePointerAddresses: true,
+ SortKeys: true,
+ }
+ timeout = 2 * time.Second
+)
+
+// dial attempts to dial the given node and perform a handshake, returning the
+// created Conn if successful.
+func (s *Suite) dial() (*Conn, error) {
+ key, _ := crypto.GenerateKey()
+ return s.dialAs(key)
+}
+
+// dialAs attempts to dial a given node and perform a handshake using the given
+// private key.
+func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) {
+ fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP()))
+ if err != nil {
+ return nil, err
+ }
+ conn := Conn{Conn: rlpx.NewConn(fd, s.Dest.Pubkey())}
+ conn.ourKey = key
+ _, err = conn.Handshake(conn.ourKey)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ conn.caps = []p2p.Cap{
+ {Name: "eth", Version: 67},
+ {Name: "eth", Version: 68},
+ }
+ conn.ourHighestProtoVersion = 68
+ return &conn, nil
+}
+
+// dialSnap creates a connection with snap/1 capability.
+func (s *Suite) dialSnap() (*Conn, error) {
+ conn, err := s.dial()
+ if err != nil {
+ return nil, fmt.Errorf("dial failed: %v", err)
+ }
+ conn.caps = append(conn.caps, p2p.Cap{Name: "snap", Version: 1})
+ conn.ourHighestSnapProtoVersion = 1
+ return conn, nil
+}
+
+// Conn represents an individual connection with a peer
+type Conn struct {
+ *rlpx.Conn
+ ourKey *ecdsa.PrivateKey
+ negotiatedProtoVersion uint
+ negotiatedSnapProtoVersion uint
+ ourHighestProtoVersion uint
+ ourHighestSnapProtoVersion uint
+ caps []p2p.Cap
+}
+
+// Read reads a packet from the connection.
+func (c *Conn) Read() (uint64, []byte, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return 0, nil, err
+ }
+ return code, data, nil
+}
+
+// ReadMsg attempts to read a devp2p message with a specific code.
+func (c *Conn) ReadMsg(proto Proto, code uint64, msg any) error {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ got, data, err := c.Read()
+ if err != nil {
+ return err
+ }
+ if protoOffset(proto)+code == got {
+ return rlp.DecodeBytes(data, msg)
+ }
+ }
+}
+
+// Write writes a eth packet to the connection.
+func (c *Conn) Write(proto Proto, code uint64, msg any) error {
+ c.SetWriteDeadline(time.Now().Add(timeout))
+ payload, err := rlp.EncodeToBytes(msg)
+ if err != nil {
+ return err
+ }
+ _, err = c.Conn.Write(protoOffset(proto)+code, payload)
+ return err
+}
+
+// ReadEth reads an Eth sub-protocol wire message.
+func (c *Conn) ReadEth() (any, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return nil, err
+ }
+ if code == pingMsg {
+ c.Write(baseProto, pongMsg, []byte{})
+ continue
+ }
+ if getProto(code) != ethProto {
+ // Read until eth message.
+ continue
+ }
+ code -= baseProtoLen
+
+ var msg any
+ switch int(code) {
+ case eth.StatusMsg:
+ msg = new(eth.StatusPacket)
+ case eth.GetBlockHeadersMsg:
+ msg = new(eth.GetBlockHeadersPacket)
+ case eth.BlockHeadersMsg:
+ msg = new(eth.BlockHeadersPacket)
+ case eth.GetBlockBodiesMsg:
+ msg = new(eth.GetBlockBodiesPacket)
+ case eth.BlockBodiesMsg:
+ msg = new(eth.BlockBodiesPacket)
+ case eth.NewBlockMsg:
+ msg = new(eth.NewBlockPacket)
+ case eth.NewBlockHashesMsg:
+ msg = new(eth.NewBlockHashesPacket)
+ case eth.TransactionsMsg:
+ msg = new(eth.TransactionsPacket)
+ case eth.NewPooledTransactionHashesMsg:
+ msg = new(eth.NewPooledTransactionHashesPacket)
+ case eth.GetPooledTransactionsMsg:
+ msg = new(eth.GetPooledTransactionsPacket)
+ case eth.PooledTransactionsMsg:
+ msg = new(eth.PooledTransactionsPacket)
+ default:
+ panic(fmt.Sprintf("unhandled eth msg code %d", code))
+ }
+ if err := rlp.DecodeBytes(data, msg); err != nil {
+ return nil, fmt.Errorf("unable to decode eth msg: %v", err)
+ }
+ return msg, nil
+ }
+}
+
+// ReadSnap reads a snap/1 response with the given id from the connection.
+func (c *Conn) ReadSnap() (any, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return nil, err
+ }
+ if getProto(code) != snapProto {
+ // Read until snap message.
+ continue
+ }
+ code -= baseProtoLen + ethProtoLen
+
+ var msg any
+ switch int(code) {
+ case snap.GetAccountRangeMsg:
+ msg = new(snap.GetAccountRangePacket)
+ case snap.AccountRangeMsg:
+ msg = new(snap.AccountRangePacket)
+ case snap.GetStorageRangesMsg:
+ msg = new(snap.GetStorageRangesPacket)
+ case snap.StorageRangesMsg:
+ msg = new(snap.StorageRangesPacket)
+ case snap.GetByteCodesMsg:
+ msg = new(snap.GetByteCodesPacket)
+ case snap.ByteCodesMsg:
+ msg = new(snap.ByteCodesPacket)
+ case snap.GetTrieNodesMsg:
+ msg = new(snap.GetTrieNodesPacket)
+ case snap.TrieNodesMsg:
+ msg = new(snap.TrieNodesPacket)
+ default:
+ panic(fmt.Errorf("unhandled snap code: %d", code))
+ }
+ if err := rlp.DecodeBytes(data, msg); err != nil {
+ return nil, fmt.Errorf("could not rlp decode message: %v", err)
+ }
+ return msg, nil
+ }
+}
+
+// peer performs both the protocol handshake and the status message
+// exchange with the node in order to peer with it.
+func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error {
+ if err := c.handshake(); err != nil {
+ return fmt.Errorf("handshake failed: %v", err)
+ }
+ if err := c.statusExchange(chain, status); err != nil {
+ return fmt.Errorf("status exchange failed: %v", err)
+ }
+ return nil
+}
+
+// handshake performs a protocol handshake with the node.
+func (c *Conn) handshake() error {
+ // Write hello to client.
+ pub0 := crypto.FromECDSAPub(&c.ourKey.PublicKey)[1:]
+ ourHandshake := &protoHandshake{
+ Version: 5,
+ Caps: c.caps,
+ ID: pub0,
+ }
+ if err := c.Write(baseProto, handshakeMsg, ourHandshake); err != nil {
+ return fmt.Errorf("write to connection failed: %v", err)
+ }
+ // Read hello from client.
+ code, data, err := c.Read()
+ if err != nil {
+ return fmt.Errorf("erroring reading handshake: %v", err)
+ }
+ switch code {
+ case handshakeMsg:
+ msg := new(protoHandshake)
+ if err := rlp.DecodeBytes(data, &msg); err != nil {
+ return fmt.Errorf("error decoding handshake msg: %v", err)
+ }
+ // Set snappy if version is at least 5.
+ if msg.Version >= 5 {
+ c.SetSnappy(true)
+ }
+ c.negotiateEthProtocol(msg.Caps)
+ if c.negotiatedProtoVersion == 0 {
+ return fmt.Errorf("could not negotiate eth protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion)
+ }
+ // If we require snap, verify that it was negotiated.
+ if c.ourHighestSnapProtoVersion != c.negotiatedSnapProtoVersion {
+ return fmt.Errorf("could not negotiate snap protocol (remote caps: %v, local snap version: %v)", msg.Caps, c.ourHighestSnapProtoVersion)
+ }
+ return nil
+ default:
+ return fmt.Errorf("bad handshake: got msg code %d", code)
+ }
+}
+
+// negotiateEthProtocol sets the Conn's eth protocol version to highest
+// advertised capability from peer.
+func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
+ var highestEthVersion uint
+ var highestSnapVersion uint
+ for _, capability := range caps {
+ switch capability.Name {
+ case "eth":
+ if capability.Version > highestEthVersion && capability.Version <= c.ourHighestProtoVersion {
+ highestEthVersion = capability.Version
+ }
+ case "snap":
+ if capability.Version > highestSnapVersion && capability.Version <= c.ourHighestSnapProtoVersion {
+ highestSnapVersion = capability.Version
+ }
+ }
+ }
+ c.negotiatedProtoVersion = highestEthVersion
+ c.negotiatedSnapProtoVersion = highestSnapVersion
+}
+
+// statusExchange performs a `Status` message exchange with the given node.
+func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error {
+loop:
+ for {
+ code, data, err := c.Read()
+ if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+ switch code {
+ case eth.StatusMsg + protoOffset(ethProto):
+ msg := new(eth.StatusPacket)
+ if err := rlp.DecodeBytes(data, &msg); err != nil {
+ return fmt.Errorf("error decoding status packet: %w", err)
+ }
+ if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want {
+ 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)
+ }
+ if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) {
+ return fmt.Errorf("wrong protocol version: have %v, want %v", have, want)
+ }
+ break loop
+ case discMsg:
+ var msg []p2p.DiscReason
+ if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
+ return errors.New("invalid disconnect message")
+ }
+ return fmt.Errorf("disconnect received: %v", pretty.Sdump(msg))
+ case pingMsg:
+ // TODO (renaynay): in the future, this should be an error
+ // (PINGs should not be a response upon fresh connection)
+ c.Write(baseProto, pongMsg, nil)
+ default:
+ return fmt.Errorf("bad status message: code %d", code)
+ }
+ }
+ // make sure eth protocol version is set for negotiation
+ if c.negotiatedProtoVersion == 0 {
+ return errors.New("eth protocol version must be set in Conn")
+ }
+ if status == nil {
+ // default status message
+ status = ð.StatusPacket{
+ ProtocolVersion: uint32(c.negotiatedProtoVersion),
+ NetworkID: chain.config.ChainID.Uint64(),
+ TD: chain.TD(),
+ Head: chain.blocks[chain.Len()-1].Hash(),
+ Genesis: chain.blocks[0].Hash(),
+ ForkID: chain.ForkID(),
+ }
+ }
+ if err := c.Write(ethProto, eth.StatusMsg, status); err != nil {
+ return fmt.Errorf("write to connection failed: %v", err)
+ }
+ return nil
+}
diff --git a/cmd/devp2p/internal/ethtest/engine.go b/cmd/devp2p/internal/ethtest/engine.go
new file mode 100644
index 0000000000..ea4fc76e6f
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/engine.go
@@ -0,0 +1,69 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package ethtest
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/golang-jwt/jwt/v4"
+)
+
+// EngineClient is a wrapper around engine-related data.
+type EngineClient struct {
+ url string
+ jwt [32]byte
+ headfcu []byte
+}
+
+// NewEngineClient creates a new engine client.
+func NewEngineClient(dir, url, jwt string) (*EngineClient, error) {
+ headfcu, err := os.ReadFile(path.Join(dir, "headfcu.json"))
+ if err != nil {
+ return nil, fmt.Errorf("failed to read headfcu: %w", err)
+ }
+ return &EngineClient{url, common.HexToHash(jwt), headfcu}, nil
+}
+
+// token returns the jwt claim token for authorization.
+func (ec *EngineClient) token() string {
+ claims := jwt.RegisteredClaims{IssuedAt: jwt.NewNumericDate(time.Now())}
+ token, _ := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(ec.jwt[:])
+ return token
+}
+
+// sendForkchoiceUpdated sends an fcu for the head of the generated chain.
+func (ec *EngineClient) sendForkchoiceUpdated() error {
+ var (
+ req, _ = http.NewRequest(http.MethodPost, ec.url, io.NopCloser(bytes.NewReader(ec.headfcu)))
+ header = make(http.Header)
+ )
+ // Set header
+ header.Set("accept", "application/json")
+ header.Set("content-type", "application/json")
+ header.Set("Authorization", fmt.Sprintf("Bearer %v", ec.token()))
+ req.Header = header
+
+ _, err := new(http.Client).Do(req)
+ return err
+}
diff --git a/cmd/devp2p/internal/ethtest/helpers.go b/cmd/devp2p/internal/ethtest/helpers.go
deleted file mode 100644
index e1dfc34256..0000000000
--- a/cmd/devp2p/internal/ethtest/helpers.go
+++ /dev/null
@@ -1,711 +0,0 @@
-// Copyright 2021 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "errors"
- "fmt"
- "net"
- "reflect"
- "strings"
- "time"
-
- "github.com/davecgh/go-spew/spew"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth/protocols/eth"
- "github.com/ethereum/go-ethereum/internal/utesting"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/p2p/rlpx"
-)
-
-var (
- pretty = spew.ConfigState{
- Indent: " ",
- DisableCapacities: true,
- DisablePointerAddresses: true,
- SortKeys: true,
- }
- timeout = 20 * time.Second
-)
-
-// dial attempts to dial the given node and perform a handshake,
-// returning the created Conn if successful.
-func (s *Suite) dial() (*Conn, error) {
- // dial
- fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP()))
- if err != nil {
- return nil, err
- }
-
- conn := Conn{Conn: rlpx.NewConn(fd, s.Dest.Pubkey())}
- // do encHandshake
- conn.ourKey, _ = crypto.GenerateKey()
- _, err = conn.Handshake(conn.ourKey)
-
- if err != nil {
- conn.Close()
- return nil, err
- }
- // set default p2p capabilities
- conn.caps = []p2p.Cap{
- {Name: "eth", Version: 67},
- {Name: "eth", Version: 68},
- }
- conn.ourHighestProtoVersion = 68
-
- return &conn, nil
-}
-
-// dialSnap creates a connection with snap/1 capability.
-func (s *Suite) dialSnap() (*Conn, error) {
- conn, err := s.dial()
- if err != nil {
- return nil, fmt.Errorf("dial failed: %v", err)
- }
-
- conn.caps = append(conn.caps, p2p.Cap{Name: "snap", Version: 1})
- conn.ourHighestSnapProtoVersion = 1
-
- return conn, nil
-}
-
-// peer performs both the protocol handshake and the status message
-// exchange with the node in order to peer with it.
-func (c *Conn) peer(chain *Chain, status *Status) error {
- if err := c.handshake(); err != nil {
- return fmt.Errorf("handshake failed: %v", err)
- }
-
- if _, err := c.statusExchange(chain, status); err != nil {
- return fmt.Errorf("status exchange failed: %v", err)
- }
-
- return nil
-}
-
-// handshake performs a protocol handshake with the node.
-func (c *Conn) handshake() error {
- defer c.SetDeadline(time.Time{})
- c.SetDeadline(time.Now().Add(10 * time.Second))
- // write hello to client
- pub0 := crypto.FromECDSAPub(&c.ourKey.PublicKey)[1:]
-
- ourHandshake := &Hello{
- Version: 5,
- Caps: c.caps,
- ID: pub0,
- }
- if err := c.Write(ourHandshake); err != nil {
- return fmt.Errorf("write to connection failed: %v", err)
- }
- // read hello from client
- switch msg := c.Read().(type) {
- case *Hello:
- // set snappy if version is at least 5
- if msg.Version >= 5 {
- c.SetSnappy(true)
- }
-
- c.negotiateEthProtocol(msg.Caps)
-
- if c.negotiatedProtoVersion == 0 {
- return fmt.Errorf("could not negotiate eth protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion)
- }
- // If we require snap, verify that it was negotiated
- if c.ourHighestSnapProtoVersion != c.negotiatedSnapProtoVersion {
- return fmt.Errorf("could not negotiate snap protocol (remote caps: %v, local snap version: %v)", msg.Caps, c.ourHighestSnapProtoVersion)
- }
-
- return nil
- default:
- return fmt.Errorf("bad handshake: %#v", msg)
- }
-}
-
-// negotiateEthProtocol sets the Conn's eth protocol version to highest
-// advertised capability from peer.
-func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
- var highestEthVersion uint
-
- var highestSnapVersion uint
-
- for _, capability := range caps {
- switch capability.Name {
- case "eth":
- if capability.Version > highestEthVersion && capability.Version <= c.ourHighestProtoVersion {
- highestEthVersion = capability.Version
- }
- case "snap":
- if capability.Version > highestSnapVersion && capability.Version <= c.ourHighestSnapProtoVersion {
- highestSnapVersion = capability.Version
- }
- }
- }
-
- c.negotiatedProtoVersion = highestEthVersion
- c.negotiatedSnapProtoVersion = highestSnapVersion
-}
-
-// statusExchange performs a `Status` message exchange with the given node.
-func (c *Conn) statusExchange(chain *Chain, status *Status) (Message, error) {
- defer c.SetDeadline(time.Time{})
- c.SetDeadline(time.Now().Add(20 * time.Second))
-
- // read status message from client
- var message Message
-loop:
- for {
- switch msg := c.Read().(type) {
- case *Status:
- if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want {
- return nil, 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 nil, fmt.Errorf("wrong TD in status: have %v want %v", have, want)
- }
- if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) {
- return nil, fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want)
- }
- if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) {
- return nil, fmt.Errorf("wrong protocol version: have %v, want %v", have, want)
- }
- message = msg
- break loop
- case *Disconnect:
- return nil, fmt.Errorf("disconnect received: %v", msg.Reason)
- case *Ping:
- c.Write(&Pong{}) // TODO (renaynay): in the future, this should be an error
- // (PINGs should not be a response upon fresh connection)
- default:
- return nil, fmt.Errorf("bad status message: %s", pretty.Sdump(msg))
- }
- }
- // make sure eth protocol version is set for negotiation
- if c.negotiatedProtoVersion == 0 {
- return nil, errors.New("eth protocol version must be set in Conn")
- }
-
- if status == nil {
- // default status message
- status = &Status{
- ProtocolVersion: uint32(c.negotiatedProtoVersion),
- NetworkID: chain.chainConfig.ChainID.Uint64(),
- TD: chain.TD(),
- Head: chain.blocks[chain.Len()-1].Hash(),
- Genesis: chain.blocks[0].Hash(),
- ForkID: chain.ForkID(),
- }
- }
-
- if err := c.Write(status); err != nil {
- return nil, fmt.Errorf("write to connection failed: %v", err)
- }
-
- return message, nil
-}
-
-// createSendAndRecvConns creates two connections, one for sending messages to the
-// node, and one for receiving messages from the node.
-func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) {
- sendConn, err := s.dial()
-
- if err != nil {
- return nil, nil, fmt.Errorf("dial failed: %v", err)
- }
-
- recvConn, err := s.dial()
-
- if err != nil {
- sendConn.Close()
- return nil, nil, fmt.Errorf("dial failed: %v", err)
- }
-
- return sendConn, recvConn, nil
-}
-
-// readAndServe serves GetBlockHeaders requests while waiting
-// on another message from the node.
-func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
- start := time.Now()
- for time.Since(start) < timeout {
- c.SetReadDeadline(time.Now().Add(10 * time.Second))
-
- msg := c.Read()
- switch msg := msg.(type) {
- case *Ping:
- c.Write(&Pong{})
- case *GetBlockHeaders:
- headers, err := chain.GetHeaders(msg)
- if err != nil {
- return errorf("could not get headers for inbound header request: %v", err)
- }
-
- resp := &BlockHeaders{
- RequestId: msg.ReqID(),
- BlockHeadersRequest: eth.BlockHeadersRequest(headers),
- }
-
- if err := c.Write(resp); err != nil {
- return errorf("could not write to connection: %v", err)
- }
- default:
- return msg
- }
- }
-
- return errorf("no message received within %v", timeout)
-}
-
-// headersRequest executes the given `GetBlockHeaders` request.
-func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint64) ([]*types.Header, error) {
- defer c.SetReadDeadline(time.Time{})
- c.SetReadDeadline(time.Now().Add(20 * time.Second))
-
- // write request
- request.RequestId = reqID
- if err := c.Write(request); err != nil {
- return nil, fmt.Errorf("could not write to connection: %v", err)
- }
-
- // wait for response
- msg := c.waitForResponse(chain, timeout, request.RequestId)
- resp, ok := msg.(*BlockHeaders)
-
- if !ok {
- return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
- }
- headers := []*types.Header(resp.BlockHeadersRequest)
- return headers, nil
-}
-
-func (c *Conn) snapRequest(msg Message, id uint64, chain *Chain) (Message, error) {
- defer c.SetReadDeadline(time.Time{})
- c.SetReadDeadline(time.Now().Add(5 * time.Second))
-
- if err := c.Write(msg); err != nil {
- return nil, fmt.Errorf("could not write to connection: %v", err)
- }
-
- return c.ReadSnap(id)
-}
-
-// headersMatch returns whether the received headers match the given request
-func headersMatch(expected []*types.Header, headers []*types.Header) bool {
- return reflect.DeepEqual(expected, headers)
-}
-
-// waitForResponse reads from the connection until a response with the expected
-// request ID is received.
-func (c *Conn) waitForResponse(chain *Chain, timeout time.Duration, requestID uint64) Message {
- for {
- msg := c.readAndServe(chain, timeout)
- if msg.ReqID() == requestID {
- return msg
- }
- }
-}
-
-// sendNextBlock broadcasts the next block in the chain and waits
-// for the node to propagate the block and import it into its chain.
-func (s *Suite) sendNextBlock() error {
- // set up sending and receiving connections
- sendConn, recvConn, err := s.createSendAndRecvConns()
- if err != nil {
- return err
- }
-
- defer sendConn.Close()
- defer recvConn.Close()
-
- if err = sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- // create new block announcement
- nextBlock := s.fullChain.blocks[s.chain.Len()]
- blockAnnouncement := &NewBlock{
- Block: nextBlock,
- TD: s.fullChain.TotalDifficultyAt(s.chain.Len()),
- }
- // send announcement and wait for node to request the header
- if err = s.testAnnounce(sendConn, recvConn, blockAnnouncement); err != nil {
- return fmt.Errorf("failed to announce block: %v", err)
- }
- // wait for client to update its chain
- if err = s.waitForBlockImport(recvConn, nextBlock); err != nil {
- return fmt.Errorf("failed to receive confirmation of block import: %v", err)
- }
- // update test suite chain
- s.chain.blocks = append(s.chain.blocks, nextBlock)
-
- return nil
-}
-
-// testAnnounce writes a block announcement to the node and waits for the node
-// to propagate it.
-func (s *Suite) testAnnounce(sendConn, receiveConn *Conn, blockAnnouncement *NewBlock) error {
- if err := sendConn.Write(blockAnnouncement); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
-
- return s.waitAnnounce(receiveConn, blockAnnouncement)
-}
-
-// waitAnnounce waits for a NewBlock or NewBlockHashes announcement from the node.
-func (s *Suite) waitAnnounce(conn *Conn, blockAnnouncement *NewBlock) error {
- for {
- switch msg := conn.readAndServe(s.chain, timeout).(type) {
- case *NewBlock:
- if !reflect.DeepEqual(blockAnnouncement.Block.Header(), msg.Block.Header()) {
- return fmt.Errorf("wrong header in block announcement: \nexpected %v "+
- "\ngot %v", blockAnnouncement.Block.Header(), msg.Block.Header())
- }
-
- if !reflect.DeepEqual(blockAnnouncement.TD, msg.TD) {
- return fmt.Errorf("wrong TD in announcement: expected %v, got %v", blockAnnouncement.TD, msg.TD)
- }
-
- return nil
- case *NewBlockHashes:
- hashes := *msg
- if blockAnnouncement.Block.Hash() != hashes[0].Hash {
- return fmt.Errorf("wrong block hash in announcement: expected %v, got %v", blockAnnouncement.Block.Hash(), hashes[0].Hash)
- }
-
- return nil
-
- // ignore tx announcements from previous tests
- case *NewPooledTransactionHashes66:
- continue
- case *NewPooledTransactionHashes:
- continue
- case *Transactions:
- continue
-
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- }
-}
-
-func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block) error {
- defer conn.SetReadDeadline(time.Time{})
- conn.SetReadDeadline(time.Now().Add(20 * time.Second))
- // create request
- req := &GetBlockHeaders{
- GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
- Origin: eth.HashOrNumber{Hash: block.Hash()},
- Amount: 1,
- },
- }
-
- // loop until BlockHeaders response contains desired block, confirming the
- // node imported the block
- for {
- requestID := uint64(54)
-
- headers, err := conn.headersRequest(req, s.chain, requestID)
- if err != nil {
- return fmt.Errorf("GetBlockHeader request failed: %v", err)
- }
- // if headers response is empty, node hasn't imported block yet, try again
- if len(headers) == 0 {
- time.Sleep(100 * time.Millisecond)
- continue
- }
-
- if !reflect.DeepEqual(block.Header(), headers[0]) {
- return fmt.Errorf("wrong header returned: wanted %v, got %v", block.Header(), headers[0])
- }
-
- return nil
- }
-}
-
-func (s *Suite) oldAnnounce() error {
- sendConn, receiveConn, err := s.createSendAndRecvConns()
- if err != nil {
- return err
- }
-
- defer sendConn.Close()
- defer receiveConn.Close()
-
- if err := sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- if err := receiveConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- // create old block announcement
- oldBlockAnnounce := &NewBlock{
- Block: s.chain.blocks[len(s.chain.blocks)/2],
- TD: s.chain.blocks[len(s.chain.blocks)/2].Difficulty(),
- }
- if err := sendConn.Write(oldBlockAnnounce); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
- // wait to see if the announcement is propagated
- switch msg := receiveConn.readAndServe(s.chain, time.Second*8).(type) {
- case *NewBlock:
- block := *msg
- if block.Block.Hash() == oldBlockAnnounce.Block.Hash() {
- return fmt.Errorf("unexpected: block propagated: %s", pretty.Sdump(msg))
- }
- case *NewBlockHashes:
- hashes := *msg
- for _, hash := range hashes {
- if hash.Hash == oldBlockAnnounce.Block.Hash() {
- return fmt.Errorf("unexpected: block announced: %s", pretty.Sdump(msg))
- }
- }
- case *Error:
- errMsg := *msg
- // check to make sure error is timeout (propagation didn't come through == test successful)
- if !strings.Contains(errMsg.String(), "timeout") {
- return fmt.Errorf("unexpected error: %v", pretty.Sdump(msg))
- }
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
-
- return nil
-}
-
-func (s *Suite) maliciousHandshakes(t *utesting.T) error {
- conn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- defer conn.Close()
-
- // write hello to client
- pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:]
-
- handshakes := []*Hello{
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: largeString(2), Version: 64},
- },
- ID: pub0,
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: append(pub0, byte(0)),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: append(pub0, pub0...),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: largeBuffer(2),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: largeString(2), Version: 64},
- },
- ID: largeBuffer(2),
- },
- }
- for i, handshake := range handshakes {
- t.Logf("Testing malicious handshake %v\n", i)
-
- if err := conn.Write(handshake); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
- // check that the peer disconnected
- for i := 0; i < 2; i++ {
- switch msg := conn.readAndServe(s.chain, 20*time.Second).(type) {
- case *Disconnect:
- case *Error:
- case *Hello:
- // Discard one hello as Hello's are sent concurrently
- continue
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- }
- // dial for the next round
- conn, err = s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- }
-
- return nil
-}
-
-func (s *Suite) maliciousStatus(conn *Conn) error {
- if err := conn.handshake(); err != nil {
- return fmt.Errorf("handshake failed: %v", err)
- }
-
- status := &Status{
- ProtocolVersion: uint32(conn.negotiatedProtoVersion),
- NetworkID: s.chain.chainConfig.ChainID.Uint64(),
- TD: largeNumber(2),
- Head: s.chain.blocks[s.chain.Len()-1].Hash(),
- Genesis: s.chain.blocks[0].Hash(),
- ForkID: s.chain.ForkID(),
- }
-
- // get status
- msg, err := conn.statusExchange(s.chain, status)
- if err != nil {
- return fmt.Errorf("status exchange failed: %v", err)
- }
-
- switch msg := msg.(type) {
- case *Status:
- default:
- return fmt.Errorf("expected status, got: %#v ", msg)
- }
-
- // wait for disconnect
- switch msg := conn.readAndServe(s.chain, timeout).(type) {
- case *Disconnect:
- return nil
- case *Error:
- return nil
- default:
- return fmt.Errorf("expected disconnect, got: %s", pretty.Sdump(msg))
- }
-}
-
-// nolint:typecheck
-func (s *Suite) hashAnnounce() error {
- // create connections
- sendConn, recvConn, err := s.createSendAndRecvConns()
- if err != nil {
- return fmt.Errorf("failed to create connections: %v", err)
- }
-
- defer sendConn.Close()
- defer recvConn.Close()
-
- if err := sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- if err := recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- // create NewBlockHashes announcement
- type anno struct {
- Hash common.Hash // Hash of one particular block being announced
- Number uint64 // Number of one particular block being announced
- }
-
- nextBlock := s.fullChain.blocks[s.chain.Len()]
- announcement := anno{Hash: nextBlock.Hash(), Number: nextBlock.Number().Uint64()}
-
- newBlockHash := &NewBlockHashes{announcement}
- if err := sendConn.Write(newBlockHash); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
-
- // Announcement sent, now wait for a header request
- msg := sendConn.Read()
- blockHeaderReq, ok := msg.(*GetBlockHeaders)
-
- if !ok {
- return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
- }
-
- if blockHeaderReq.Amount != 1 {
- return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount)
- }
-
- if blockHeaderReq.Origin.Hash != announcement.Hash {
- return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v",
- pretty.Sdump(announcement),
- pretty.Sdump(blockHeaderReq))
- }
-
- err = sendConn.Write(&BlockHeaders{
- RequestId: blockHeaderReq.ReqID(),
- BlockHeadersRequest: eth.BlockHeadersRequest{nextBlock.Header()},
- })
-
- if err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
-
- // wait for block announcement
- msg = recvConn.readAndServe(s.chain, timeout)
- switch msg := msg.(type) {
- case *NewBlockHashes:
- hashes := *msg
- if len(hashes) != 1 {
- return fmt.Errorf("unexpected new block hash announcement: wanted 1 announcement, got %d", len(hashes))
- }
-
- if nextBlock.Hash() != hashes[0].Hash {
- return fmt.Errorf("unexpected block hash announcement, wanted %v, got %v", nextBlock.Hash(),
- hashes[0].Hash)
- }
-
- case *NewBlock:
- // node should only propagate NewBlock without having requested the body if the body is empty
- nextBlockBody := nextBlock.Body()
- if len(nextBlockBody.Transactions) != 0 || len(nextBlockBody.Uncles) != 0 {
- return fmt.Errorf("unexpected non-empty new block propagated: %s", pretty.Sdump(msg))
- }
-
- if msg.Block.Hash() != nextBlock.Hash() {
- return fmt.Errorf("mismatched hash of propagated new block: wanted %v, got %v",
- nextBlock.Hash(), msg.Block.Hash())
- }
- // check to make sure header matches header that was sent to the node
- if !reflect.DeepEqual(nextBlock.Header(), msg.Block.Header()) {
- return fmt.Errorf("incorrect header received: wanted %v, got %v", nextBlock.Header(), msg.Block.Header())
- }
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- // confirm node imported block
- if err := s.waitForBlockImport(recvConn, nextBlock); err != nil {
- return fmt.Errorf("error waiting for node to import new block: %v", err)
- }
- // update the chain
- s.chain.blocks = append(s.chain.blocks, nextBlock)
-
- return nil
-}
diff --git a/cmd/devp2p/internal/ethtest/large.go b/cmd/devp2p/internal/ethtest/large.go
deleted file mode 100644
index 6de7e886ad..0000000000
--- a/cmd/devp2p/internal/ethtest/large.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "crypto/rand"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-// largeNumber returns a very large big.Int.
-func largeNumber(megabytes int) *big.Int {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
-
- bigint := new(big.Int)
- bigint.SetBytes(buf)
-
- return bigint
-}
-
-// largeBuffer returns a very large buffer.
-func largeBuffer(megabytes int) []byte {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
-
- return buf
-}
-
-// largeString returns a very large string.
-func largeString(megabytes int) string {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
-
- return hexutil.Encode(buf)
-}
-
-func largeBlock() *types.Block {
- return types.NewBlockWithHeader(largeHeader())
-}
-
-// Returns a random hash
-func randHash() common.Hash {
- var h common.Hash
-
- rand.Read(h[:])
-
- return h
-}
-
-func largeHeader() *types.Header {
- return &types.Header{
- MixDigest: randHash(),
- ReceiptHash: randHash(),
- TxHash: randHash(),
- Nonce: types.BlockNonce{},
- Extra: []byte{},
- Bloom: types.Bloom{},
- GasUsed: 0,
- Coinbase: common.Address{},
- GasLimit: 0,
- UncleHash: types.EmptyUncleHash,
- Time: 1337,
- ParentHash: randHash(),
- Root: randHash(),
- Number: largeNumber(2),
- Difficulty: largeNumber(2),
- }
-}
diff --git a/cmd/devp2p/internal/ethtest/mkchain.sh b/cmd/devp2p/internal/ethtest/mkchain.sh
new file mode 100644
index 0000000000..b9253e8ca7
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/mkchain.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+hivechain generate \
+ --fork-interval 6 \
+ --tx-interval 1 \
+ --length 500 \
+ --outdir testdata \
+ --lastfork cancun \
+ --outputs accounts,genesis,chain,headstate,txinfo,headblock,headfcu,newpayload,forkenv
diff --git a/cmd/devp2p/internal/ethtest/protocol.go b/cmd/devp2p/internal/ethtest/protocol.go
new file mode 100644
index 0000000000..f5f5f7e489
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/protocol.go
@@ -0,0 +1,87 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+package ethtest
+
+import (
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Unexported devp2p message codes from p2p/peer.go.
+const (
+ handshakeMsg = 0x00
+ discMsg = 0x01
+ pingMsg = 0x02
+ pongMsg = 0x03
+)
+
+// Unexported devp2p protocol lengths from p2p package.
+const (
+ baseProtoLen = 16
+ ethProtoLen = 17
+ snapProtoLen = 8
+)
+
+// Unexported handshake structure from p2p/peer.go.
+type protoHandshake struct {
+ Version uint64
+ Name string
+ Caps []p2p.Cap
+ ListenPort uint64
+ ID []byte
+ Rest []rlp.RawValue `rlp:"tail"`
+}
+
+type Hello = protoHandshake
+
+// Proto is an enum representing devp2p protocol types.
+type Proto int
+
+const (
+ baseProto Proto = iota
+ ethProto
+ snapProto
+)
+
+// getProto returns the protocol a certain message code is associated with
+// (assuming the negotiated capabilities are exactly {eth,snap})
+func getProto(code uint64) Proto {
+ switch {
+ case code < baseProtoLen:
+ return baseProto
+ case code < baseProtoLen+ethProtoLen:
+ return ethProto
+ case code < baseProtoLen+ethProtoLen+snapProtoLen:
+ return snapProto
+ default:
+ panic("unhandled msg code beyond last protocol")
+ }
+}
+
+// protoOffset will return the offset at which the specified protocol's messages
+// begin.
+func protoOffset(proto Proto) uint64 {
+ switch proto {
+ case baseProto:
+ return 0
+ case ethProto:
+ return baseProtoLen
+ case snapProto:
+ return baseProtoLen + ethProtoLen
+ default:
+ panic("unhandled protocol")
+ }
+}
diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go
index 62a72d7830..c8dd7458fd 100644
--- a/cmd/devp2p/internal/ethtest/snap.go
+++ b/cmd/devp2p/internal/ethtest/snap.go
@@ -20,9 +20,12 @@ import (
"bytes"
"errors"
"fmt"
+ "math/big"
"math/rand"
+ "reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@@ -32,6 +35,13 @@ import (
"golang.org/x/crypto/sha3"
)
+func (c *Conn) snapRequest(code uint64, msg any) (any, error) {
+ if err := c.Write(snapProto, code, msg); err != nil {
+ return nil, fmt.Errorf("could not write to connection: %v", err)
+ }
+ return c.ReadSnap()
+}
+
func (s *Suite) TestSnapStatus(t *utesting.T) {
conn, err := s.dialSnap()
if err != nil {
@@ -46,75 +56,269 @@ func (s *Suite) TestSnapStatus(t *utesting.T) {
}
type accRangeTest struct {
- nBytes uint64
- root common.Hash
- origin common.Hash
- limit common.Hash
+ nBytes uint64
+ root common.Hash
+ startingHash common.Hash
+ limitHash common.Hash
expAccounts int
expFirst common.Hash
expLast common.Hash
+
+ desc string
}
// TestSnapGetAccountRange various forms of GetAccountRange requests.
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
var (
- root = s.chain.RootAt(999)
- ffHash = common.MaxHash
- zero = common.Hash{}
- firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
- firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- firstKeyPlus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b")
- secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
- storageRoot = common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790")
+ ffHash = common.MaxHash
+ zero = common.Hash{}
+
+ // test values derived from chain/ account dump
+ root = s.chain.Head().Root()
+ headstate = s.chain.AccountsInHashOrder()
+ firstKey = common.BytesToHash(headstate[0].AddressHash)
+ secondKey = common.BytesToHash(headstate[1].AddressHash)
+ storageRoot = findNonEmptyStorageRoot(headstate)
)
- for i, tc := range []accRangeTest{
+ tests := []accRangeTest{
// Tests decreasing the number of bytes
- {4000, root, zero, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")},
- {3000, root, zero, ffHash, 57, firstKey, common.HexToHash("0x9b63fa753ece5cb90657d02ecb15df4dc1508d8c1d187af1bf7f1a05e747d3c7")},
- {2000, root, zero, ffHash, 38, firstKey, common.HexToHash("0x5e6140ecae4354a9e8f47559a8c6209c1e0e69cb077b067b528556c11698b91f")},
- {1, root, zero, ffHash, 1, firstKey, firstKey},
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"),
+ desc: "In this test, we request the entire state range, but limit the response to 4000 bytes.",
+ },
+ {
+ nBytes: 3000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 65,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6"),
+ desc: "In this test, we request the entire state range, but limit the response to 3000 bytes.",
+ },
+ {
+ nBytes: 2000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 44,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595"),
+ desc: "In this test, we request the entire state range, but limit the response to 2000 bytes.",
+ },
+ {
+ nBytes: 1,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, we request the entire state range, but limit the response to 1 byte.
+The server should return the first account of the state.`,
+ },
+ {
+ nBytes: 0,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `Here we request with a responseBytes limit of zero.
+The server should return one account.`,
+ },
// Tests variations of the range
- //
- // [00b to firstkey]: should return [firstkey, secondkey], where secondkey is out of bounds
- {4000, root, common.HexToHash("0x00bf000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b"), 2, firstKey, secondKey},
- // [00b0 to 0bf0]: where both are before firstkey. Should return firstKey (even though it's out of bounds)
- {4000, root, common.HexToHash("0x00b0000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf100000000000000000000000000000000000000000000000000000000000"), 1, firstKey, firstKey},
- {4000, root, zero, zero, 1, firstKey, firstKey},
- {4000, root, firstKey, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")},
- {4000, root, firstKeyPlus1, ffHash, 76, secondKey, common.HexToHash("0xd28f55d3b994f16389f36944ad685b48e0fc3f8fbe86c3ca92ebecadf16a783f")},
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, -500),
+ limitHash: hashAdd(firstKey, 1),
+ expAccounts: 2,
+ expFirst: firstKey,
+ expLast: secondKey,
+ desc: `In this test, we request a range where startingHash is before the first available
+account key, and limitHash is after. The server should return the first and second
+account of the state (because the second account is the 'next available').`,
+ },
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, -500),
+ limitHash: hashAdd(firstKey, -450),
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `Here we request range where both bounds are before the first available account key.
+This should return the first account (even though it's out of bounds).`,
+ },
+
+ // More range tests:
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: zero,
+ limitHash: zero,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, both startingHash and limitHash are zero.
+The server should return the first available account.`,
+ },
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"),
+ desc: `In this test, startingHash is exactly the first available account key.
+The server should return the first available account of the state as the first item.`,
+ },
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, 1),
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: secondKey,
+ expLast: common.HexToHash("0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"),
+ desc: `In this test, startingHash is after the first available key.
+The server should return the second account of the state as the first item.`,
+ },
// Test different root hashes
- //
- // A stateroot that does not exist
- {4000, common.Hash{0x13, 37}, zero, ffHash, 0, zero, zero},
+
+ {
+ nBytes: 4000,
+ root: common.Hash{0x13, 0x37},
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests a non-existent state root.`,
+ },
+
// The genesis stateroot (we expect it to not be served)
- {4000, s.chain.RootAt(0), zero, ffHash, 0, zero, zero},
- // A 127 block old stateroot, expected to be served
- {4000, s.chain.RootAt(999 - 127), zero, ffHash, 77, firstKey, common.HexToHash("0xe4c6fdef5dd4e789a2612390806ee840b8ec0fe52548f8b4efe41abb20c37aac")},
- // A root which is not actually an account root, but a storage root
- {4000, storageRoot, zero, ffHash, 0, zero, zero},
+ {
+ nBytes: 4000,
+ root: s.chain.RootAt(0),
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests data at the state root of the genesis block. We expect the
+server to return no data because genesis is older than 127 blocks.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: s.chain.RootAt(int(s.chain.Head().Number().Uint64()) - 127),
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 84,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3"),
+ desc: `This test requests data at a state root that is 127 blocks old.
+We expect the server to have this state available.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: storageRoot,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests data at a state root that is actually the storage root of
+an existing account. The server is supposed to ignore this request.`,
+ },
// And some non-sensical requests
- //
- // range from [0xFF to 0x00], wrong order. Expect not to be serviced
- {4000, root, ffHash, zero, 0, zero, zero},
- // range from [firstkey, firstkey-1], wrong order. Expect to get first key.
- {4000, root, firstKey, firstKeyMinus1, 1, firstKey, firstKey},
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: ffHash,
+ limitHash: zero,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `In this test, the startingHash is after limitHash (wrong order). The server
+should ignore this invalid request.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: hashAdd(firstKey, -1),
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, the startingHash is the first available key, and limitHash is
+a key before startingHash (wrong order). The server should return the first available key.`,
+ },
+
// range from [firstkey, 0], wrong order. Expect to get first key.
- {4000, root, firstKey, zero, 1, firstKey, firstKey},
- // Max bytes: 0. Expect to deliver one account.
- {0, root, zero, ffHash, 1, firstKey, firstKey},
- } {
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: zero,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, the startingHash is the first available key and limitHash is zero.
+(wrong order). The server should return the first available key.`,
+ },
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" range: %#x - %#x", tc.startingHash, tc.limitHash)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetAccountRange(t, &tc); err != nil {
- t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\nfailed: %v", i, tc.root, tc.origin, tc.limit, tc.nBytes, err)
+ t.Errorf("test %d failed: %v", i, err)
}
}
}
+func hashAdd(h common.Hash, n int64) common.Hash {
+ hb := h.Big()
+ return common.BigToHash(hb.Add(hb, big.NewInt(n)))
+}
+
+func findNonEmptyStorageRoot(accounts []state.DumpAccount) common.Hash {
+ for i := range accounts {
+ if len(accounts[i].Storage) != 0 {
+ return common.BytesToHash(accounts[i].Root)
+ }
+ }
+ panic("can't find account with non-empty storage")
+}
+
type stRangesTest struct {
root common.Hash
accounts []common.Hash
@@ -122,88 +326,125 @@ type stRangesTest struct {
limit []byte
nBytes uint64
- expSlots int
+ expSlots [][]*snap.StorageData
+
+ desc string
}
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
var (
+ acct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067")
+ acctHash = common.BytesToHash(s.chain.state[acct].AddressHash)
ffHash = common.MaxHash
zero = common.Hash{}
- firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
+ blockroot = s.chain.Head().Root()
)
- for i, tc := range []stRangesTest{
+ // These are the storage slots of the test account, encoded as snap response data.
+ acctSlots := []*snap.StorageData{
{
- root: s.chain.RootAt(999),
- accounts: []common.Hash{secondKey, firstKey},
- origin: zero[:],
- limit: ffHash[:],
- nBytes: 500,
- expSlots: 0,
+ Hash: common.HexToHash("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
+ Body: []byte{0x02},
},
+ {
+ Hash: common.HexToHash("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"),
+ Body: []byte{0x01},
+ },
+ {
+ Hash: common.HexToHash("0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b"),
+ Body: []byte{0x03},
+ },
+ }
+ tests := []stRangesTest{
/*
Some tests against this account:
- {
- "balance": "0",
- "nonce": 1,
- "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
- "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
- "storage": {
- "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
- "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
- "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
- },
- "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"
+
+ "0x8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "balance": "1",
+ "nonce": 1,
+ "root": "0xe318dff15b33aa7f2f12d5567d58628e3e3f2e8859e46b56981a4083b391da17",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ // Note: keys below are hashed!!!
+ "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
+ "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
+ "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
+ },
+ "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"
}
*/
+
{ // [:] -> [slot1, slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This request has a range of 00..ff.
+The server should return all storage slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: zero[:],
limit: ffHash[:],
nBytes: 500,
- expSlots: 3,
+ expSlots: [][]*snap.StorageData{acctSlots},
},
+
{ // [slot1:] -> [slot1, slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests slots starting at the first available key.
+The server should return all storage slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
limit: ffHash[:],
- nBytes: 500,
- expSlots: 3,
+ nBytes: 1000,
+ expSlots: [][]*snap.StorageData{acctSlots},
},
- { // [slot1+ :] -> [slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+
+ { // [slot1+:] -> [slot2, slot3]
+ desc: `This test requests slots starting at a key one past the first available key.
+The server should return the remaining two slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf"),
limit: ffHash[:],
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[1:]},
},
+
{ // [slot1:slot2] -> [slot1, slot2]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests a range which is exactly the first and second available key.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"),
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[:2]},
},
+
{ // [slot1+:slot2+] -> [slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests a range where limitHash is after the second, but before the third slot
+of the test account. The server should return slots [2,3] (i.e. the 'next available' needs to be returned).`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7"),
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[1:]},
},
- } {
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" accounts: %x", tc.accounts)
+ t.Logf(" range: %#x - %#x", tc.origin, tc.limit)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetStorageRanges(t, &tc); err != nil {
- t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\n #accounts: %d\nfailed: %v",
- i, tc.root, tc.origin, tc.limit, tc.nBytes, len(tc.accounts), err)
+ t.Errorf(" failed: %v", err)
}
}
}
@@ -213,87 +454,92 @@ type byteCodesTest struct {
hashes []common.Hash
expHashes int
+
+ desc string
}
// TestSnapGetByteCodes various forms of GetByteCodes requests.
func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
- // The halfchain import should yield these bytecodes
- var hcBytecodes []common.Hash
- for _, s := range []string{
- "0x200c90460d8b0063210d5f5b9918e053c8f2c024485e0f1b48be8b1fc71b1317",
- "0x20ba67ed4ac6aff626e0d1d4db623e2fada9593daeefc4a6eb4b70e6cff986f3",
- "0x24b5b4902cb3d897c1cee9f16be8e897d8fa277c04c6dc8214f18295fca5de44",
- "0x320b9d0a2be39b8a1c858f9f8cb96b1df0983071681de07ded3a7c0d05db5fd6",
- "0x48cb0d5275936a24632babc7408339f9f7b051274809de565b8b0db76e97e03c",
- "0x67c7a6f5cdaa43b4baa0e15b2be63346d1b9ce9f2c3d7e5804e0cacd44ee3b04",
- "0x6d8418059bdc8c3fabf445e6bfc662af3b6a4ae45999b953996e42c7ead2ab49",
- "0x7043422e5795d03f17ee0463a37235258e609fdd542247754895d72695e3e142",
- "0x727f9e6f0c4bac1ff8d72c2972122d9c8d37ccb37e04edde2339e8da193546f1",
- "0x86ccd5e23c78568a8334e0cebaf3e9f48c998307b0bfb1c378cee83b4bfb29cb",
- "0x8fc89b00d6deafd4c4279531e743365626dbfa28845ec697919d305c2674302d",
- "0x92cfc353bcb9746bb6f9996b6b9df779c88af2e9e0eeac44879ca19887c9b732",
- "0x941b4872104f0995a4898fcf0f615ea6bf46bfbdfcf63ea8f2fd45b3f3286b77",
- "0xa02fe8f41159bb39d2b704c633c3d6389cf4bfcb61a2539a9155f60786cf815f",
- "0xa4b94e0afdffcb0af599677709dac067d3145489ea7aede57672bee43e3b7373",
- "0xaf4e64edd3234c1205b725e42963becd1085f013590bd7ed93f8d711c5eb65fb",
- "0xb69a18fa855b742031420081999086f6fb56c3930ae8840944e8b8ae9931c51e",
- "0xc246c217bc73ce6666c93a93a94faa5250564f50a3fdc27ea74c231c07fe2ca6",
- "0xcd6e4ab2c3034df2a8a1dfaaeb1c4baecd162a93d22de35e854ee2945cbe0c35",
- "0xe24b692d09d6fc2f3d1a6028c400a27c37d7cbb11511907c013946d6ce263d3b",
- "0xe440c5f0e8603fd1ed25976eee261ccee8038cf79d6a4c0eb31b2bf883be737f",
- "0xe6eacbc509203d21ac814b350e72934fde686b7f673c19be8cf956b0c70078ce",
- "0xe8530de4371467b5be7ea0e69e675ab36832c426d6c1ce9513817c0f0ae1486b",
- "0xe85d487abbbc83bf3423cf9731360cf4f5a37220e18e5add54e72ee20861196a",
- "0xf195ea389a5eea28db0be93660014275b158963dec44af1dfa7d4743019a9a49",
- } {
- hcBytecodes = append(hcBytecodes, common.HexToHash(s))
- }
+ var (
+ allHashes = s.chain.CodeHashes()
+ headRoot = s.chain.Head().Root()
+ genesisRoot = s.chain.RootAt(0)
+ )
- for i, tc := range []byteCodesTest{
+ tests := []byteCodesTest{
// A few stateroots
{
- nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(999)},
+ desc: `Here we request state roots as code hashes. The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{genesisRoot, headRoot},
expHashes: 0,
},
{
- nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(0)},
+ desc: `Here we request the genesis state root (which is not an existing code hash) two times. The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{genesisRoot, genesisRoot},
expHashes: 0,
},
// Empties
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyRootHash},
+ desc: `Here we request the empty state root (which is not an existing code hash). The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyRootHash},
expHashes: 0,
},
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash},
+ desc: `Here we request the empty code hash. The server should deliver an empty response item.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyCodeHash},
expHashes: 1,
},
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
+ desc: `In this test, we request the empty code hash three times. The server should deliver the empty item three times.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
expHashes: 3,
},
// The existing bytecodes
{
- nBytes: 10000, hashes: hcBytecodes,
- expHashes: len(hcBytecodes),
+ desc: `Here we request all available contract codes. The server should deliver them all in one response.`,
+ nBytes: 100000,
+ hashes: allHashes,
+ expHashes: len(allHashes),
},
// The existing, with limited byte arg
{
- nBytes: 1, hashes: hcBytecodes,
+ desc: `In this test, the request has a bytes limit of one. The server should deliver one item.`,
+ nBytes: 1,
+ hashes: allHashes,
expHashes: 1,
},
{
- nBytes: 0, hashes: hcBytecodes,
+ desc: `In this test, the request has a bytes limit of zero. The server should deliver one item.`,
+ nBytes: 0,
+ hashes: allHashes,
expHashes: 1,
},
+ // Request the same hash multiple times.
{
- nBytes: 1000, hashes: []common.Hash{hcBytecodes[0], hcBytecodes[0], hcBytecodes[0], hcBytecodes[0]},
+ desc: `This test requests the same code hash multiple times. The server should deliver it multiple times.`,
+ nBytes: 1000,
+ hashes: []common.Hash{allHashes[0], allHashes[0], allHashes[0], allHashes[0]},
expHashes: 4,
},
- } {
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" hashes: %x", tc.hashes)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetByteCodes(t, &tc); err != nil {
- t.Errorf("test %d \n bytes: %d\n #hashes: %d\nfailed: %v", i, tc.nBytes, len(tc.hashes), err)
+ t.Errorf("failed: %v", err)
}
}
}
@@ -303,8 +549,10 @@ type trieNodesTest struct {
paths []snap.TrieNodePathSet
nBytes uint64
- expHashes []common.Hash
- expReject bool
+ expHashes []common.Hash // expected response
+ expReject bool // if true, request should be rejected
+
+ desc string
}
func decodeNibbles(nibbles []byte, bytes []byte) {
@@ -355,33 +603,35 @@ func hexToCompact(hex []byte) []byte {
// TestSnapTrieNodes various forms of GetTrieNodes requests.
func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
- key := common.FromHex("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- // helper function to iterate the key, and generate the compact-encoded
- // trie paths along the way.
- pathTo := func(length int) snap.TrieNodePathSet {
- hex := keybytesToHex(key)[:length]
- hex[len(hex)-1] = 0 // remove term flag
- hKey := hexToCompact(hex)
- return snap.TrieNodePathSet{hKey}
- }
+ var (
+ // This is the known address of the snap storage testing contract.
+ storageAcct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067")
+ storageAcctHash = common.BytesToHash(s.chain.state[storageAcct].AddressHash)
+ // This is the known address of an existing account.
+ key = common.FromHex("0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9")
- var accPaths []snap.TrieNodePathSet
+ empty = types.EmptyCodeHash
+ accPaths []snap.TrieNodePathSet
+ )
for i := 1; i <= 65; i++ {
- accPaths = append(accPaths, pathTo(i))
+ accPaths = append(accPaths, makeSnapPath(key, i))
}
- empty := types.EmptyCodeHash
- for i, tc := range []trieNodesTest{
+ tests := []trieNodesTest{
{
- root: s.chain.RootAt(999),
+ desc: `In this test, we send an empty request to the node.`,
+ root: s.chain.Head().Root(),
paths: nil,
nBytes: 500,
expHashes: nil,
},
+
{
- root: s.chain.RootAt(999),
+ desc: `In this test, we send a request containing an empty path-set.
+The server should reject the request.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{}, // zero-length pathset should 'abort' and kick us off
{[]byte{0}},
@@ -390,18 +640,21 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
expHashes: []common.Hash{},
expReject: true,
},
+
{
- root: s.chain.RootAt(999),
+ desc: `Here we request the root node of the trie. The server should respond with the root node.`,
+ root: s.chain.RootAt(int(s.chain.Head().NumberU64() - 1)),
paths: []snap.TrieNodePathSet{
{[]byte{0}},
{[]byte{1}, []byte{0}},
},
- nBytes: 5000,
- //0x6b3724a41b8c38b46d4d02fba2bb2074c47a507eb16a9a4b978f91d32e406faf
- expHashes: []common.Hash{s.chain.RootAt(999)},
+ nBytes: 5000,
+ expHashes: []common.Hash{s.chain.RootAt(int(s.chain.Head().NumberU64() - 1))},
},
+
{ // nonsensically long path
- root: s.chain.RootAt(999),
+ desc: `In this test, we request a very long trie node path. The server should respond with an empty node (keccak256("")).`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}},
@@ -409,25 +662,19 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
nBytes: 5000,
expHashes: []common.Hash{common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")},
},
- {
- root: s.chain.RootAt(0),
- paths: []snap.TrieNodePathSet{
- {[]byte{0}},
- {[]byte{1}, []byte{0}},
- },
- nBytes: 5000,
- expHashes: []common.Hash{
- common.HexToHash("0x1ee1bb2fbac4d46eab331f3e8551e18a0805d084ed54647883aa552809ca968d"),
- },
- },
+
{
// The leaf is only a couple of levels down, so the continued trie traversal causes lookup failures.
- root: s.chain.RootAt(999),
+ desc: `Here we request some known accounts from the state.`,
+ root: s.chain.Head().Root(),
paths: accPaths,
nBytes: 5000,
expHashes: []common.Hash{
- common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"),
- common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"),
+ // It's a bit unfortunate these are hard-coded, but the result depends on
+ // a lot of aspects of the state trie and can't be guessed in a simple
+ // way. So you'll have to update this when the test chain is changed.
+ common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"),
+ common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"),
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
@@ -435,39 +682,32 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty},
},
+
{
- // Basically the same as above, with different ordering
- root: s.chain.RootAt(999),
+ desc: `In this test, we request some known accounts in state. The requested paths are NOT in key order.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
accPaths[10], accPaths[1], accPaths[0],
},
nBytes: 5000,
+ // As with the previous test, this result depends on the whole tree and will have to
+ // be updated when the test chain is changed.
expHashes: []common.Hash{
empty,
- common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"),
- common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"),
+ common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"),
+ common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"),
},
},
+
+ // Storage tests.
+ // These use the known storage test account.
+
{
- /*
- A test against this account, requesting trie nodes for the storage trie
- {
- "balance": "0",
- "nonce": 1,
- "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
- "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
- "storage": {
- "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
- "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
- "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
- },
- "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"
- }
- */
- root: s.chain.RootAt(999),
+ desc: `This test requests the storage root node of a known account.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{
- common.FromHex("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"),
+ storageAcctHash[:],
[]byte{0},
},
},
@@ -476,14 +716,50 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"),
},
},
- } {
+
+ {
+ desc: `This test requests multiple storage nodes of a known account.`,
+ root: s.chain.Head().Root(),
+ paths: []snap.TrieNodePathSet{
+ {
+ storageAcctHash[:],
+ []byte{0},
+ []byte{0x1b},
+ },
+ },
+ nBytes: 5000,
+ expHashes: []common.Hash{
+ common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"),
+ common.HexToHash("0xf4984a11f61a2921456141df88de6e1a710d28681b91af794c5a721e47839cd7"),
+ },
+ },
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" paths: %x", tc.paths)
+ t.Logf(" responseBytes: %d", tc.nBytes)
+
if err := s.snapGetTrieNodes(t, &tc); err != nil {
- t.Errorf("test %d \n #hashes %x\n root: %#x\n bytes: %d\nfailed: %v", i, len(tc.expHashes), tc.root, tc.nBytes, err)
+ t.Errorf(" failed: %v", err)
}
}
}
+func makeSnapPath(key []byte, length int) snap.TrieNodePathSet {
+ hex := keybytesToHex(key)[:length]
+ hex[len(hex)-1] = 0 // remove term flag
+ hKey := hexToCompact(hex)
+ return snap.TrieNodePathSet{hKey}
+}
+
func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
conn, err := s.dialSnap()
if err != nil {
@@ -496,25 +772,22 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
t.Fatalf("peering failed: %v", err)
}
// write request
- req := &GetAccountRange{
+ req := &snap.GetAccountRangePacket{
ID: uint64(rand.Int63()),
Root: tc.root,
- Origin: tc.origin,
- Limit: tc.limit,
+ Origin: tc.startingHash,
+ Limit: tc.limitHash,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetAccountRangeMsg, req)
if err != nil {
return fmt.Errorf("account range request failed: %v", err)
}
- var res *snap.AccountRangePacket
-
- if r, ok := resp.(*AccountRange); !ok {
- return fmt.Errorf("account range response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.AccountRangePacket)(r)
+ res, ok := msg.(*snap.AccountRangePacket)
+ if !ok {
+ return fmt.Errorf("account range response wrong: %T %v", msg, msg)
}
if exp, got := tc.expAccounts, len(res.Accounts); exp != got {
@@ -562,7 +835,7 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
}
proofdb := nodes.Set()
- _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], keys, accounts, proofdb)
+ _, err = trie.VerifyRangeProof(tc.root, tc.startingHash[:], keys, accounts, proofdb)
return err
}
@@ -577,8 +850,9 @@ func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
+
// write request
- req := &GetStorageRanges{
+ req := &snap.GetStorageRangesPacket{
ID: uint64(rand.Int63()),
Root: tc.root,
Accounts: tc.accounts,
@@ -587,23 +861,19 @@ func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error {
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetStorageRangesMsg, req)
if err != nil {
return fmt.Errorf("account range request failed: %v", err)
}
- var res *snap.StorageRangesPacket
+ res, ok := msg.(*snap.StorageRangesPacket)
+ if !ok {
- if r, ok := resp.(*StorageRanges); !ok {
- return fmt.Errorf("account range response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.StorageRangesPacket)(r)
+ return fmt.Errorf("account range response wrong: %T %v", msg, msg)
}
- gotSlots := 0
// Ensure the ranges are monotonically increasing
for i, slots := range res.Slots {
- gotSlots += len(slots)
for j := 1; j < len(slots); j++ {
if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 {
@@ -612,8 +882,20 @@ func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error {
}
}
- if exp, got := tc.expSlots, gotSlots; exp != got {
- return fmt.Errorf("expected %d slots, got %d", exp, got)
+ // Compute expected slot hashes.
+ var expHashes [][]common.Hash
+ for _, acct := range tc.expSlots {
+ var list []common.Hash
+ for _, s := range acct {
+ list = append(list, s.Hash)
+ }
+ expHashes = append(expHashes, list)
+ }
+
+ // Check response.
+ if !reflect.DeepEqual(res.Slots, tc.expSlots) {
+ t.Log(" expected slot hashes:", expHashes)
+ return fmt.Errorf("wrong storage slots in response: %#v", res.Slots)
}
return nil
@@ -631,28 +913,25 @@ func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error {
t.Fatalf("peering failed: %v", err)
}
// write request
- req := &GetByteCodes{
+ req := &snap.GetByteCodesPacket{
ID: uint64(rand.Int63()),
Hashes: tc.hashes,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetByteCodesMsg, req)
if err != nil {
return fmt.Errorf("getBytecodes request failed: %v", err)
}
- var res *snap.ByteCodesPacket
-
- if r, ok := resp.(*ByteCodes); !ok {
- return fmt.Errorf("bytecodes response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.ByteCodesPacket)(r)
+ res, ok := msg.(*snap.ByteCodesPacket)
+ if !ok {
+ return fmt.Errorf("bytecodes response wrong: %T %v", msg, msg)
}
if exp, got := tc.expHashes, len(res.Codes); exp != got {
for i, c := range res.Codes {
- fmt.Printf("%d. %#x\n", i, c)
+ t.Logf("%d. %#x\n", i, c)
}
return fmt.Errorf("expected %d bytecodes, got %d", exp, got)
@@ -700,15 +979,16 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // write request
- req := &GetTrieNodes{
+
+ // write0 request
+ req := &snap.GetTrieNodesPacket{
ID: uint64(rand.Int63()),
Root: tc.root,
Paths: tc.paths,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetTrieNodesMsg, req)
if err != nil {
if tc.expReject {
return nil
@@ -717,12 +997,9 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
return fmt.Errorf("trienodes request failed: %v", err)
}
- var res *snap.TrieNodesPacket
-
- if r, ok := resp.(*TrieNodes); !ok {
- return fmt.Errorf("trienodes response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.TrieNodesPacket)(r)
+ res, ok := msg.(*snap.TrieNodesPacket)
+ if !ok {
+ return fmt.Errorf("trienodes response wrong: %T %v", msg, msg)
}
// Check the correctness
@@ -743,7 +1020,7 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
hasher.Read(hash)
if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) {
- fmt.Printf("hash %d wrong, got %#x, want %#x\n", i, got, want)
+ t.Logf(" hash %d wrong, got %#x, want %#x\n", i, got, want)
err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want)
}
}
diff --git a/cmd/devp2p/internal/ethtest/snapTypes.go b/cmd/devp2p/internal/ethtest/snapTypes.go
deleted file mode 100644
index 6bcaa9291a..0000000000
--- a/cmd/devp2p/internal/ethtest/snapTypes.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import "github.com/ethereum/go-ethereum/eth/protocols/snap"
-
-// GetAccountRange represents an account range query.
-type GetAccountRange snap.GetAccountRangePacket
-
-func (msg GetAccountRange) Code() int { return 33 }
-func (msg GetAccountRange) ReqID() uint64 { return msg.ID }
-
-type AccountRange snap.AccountRangePacket
-
-func (msg AccountRange) Code() int { return 34 }
-func (msg AccountRange) ReqID() uint64 { return msg.ID }
-
-type GetStorageRanges snap.GetStorageRangesPacket
-
-func (msg GetStorageRanges) Code() int { return 35 }
-func (msg GetStorageRanges) ReqID() uint64 { return msg.ID }
-
-type StorageRanges snap.StorageRangesPacket
-
-func (msg StorageRanges) Code() int { return 36 }
-func (msg StorageRanges) ReqID() uint64 { return msg.ID }
-
-type GetByteCodes snap.GetByteCodesPacket
-
-func (msg GetByteCodes) Code() int { return 37 }
-func (msg GetByteCodes) ReqID() uint64 { return msg.ID }
-
-type ByteCodes snap.ByteCodesPacket
-
-func (msg ByteCodes) Code() int { return 38 }
-func (msg ByteCodes) ReqID() uint64 { return msg.ID }
-
-type GetTrieNodes snap.GetTrieNodesPacket
-
-func (msg GetTrieNodes) Code() int { return 39 }
-func (msg GetTrieNodes) ReqID() uint64 { return msg.ID }
-
-type TrieNodes snap.TrieNodesPacket
-
-func (msg TrieNodes) Code() int { return 40 }
-func (msg TrieNodes) ReqID() uint64 { return msg.ID }
diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go
index 533e38a3d1..8e676ce6e6 100644
--- a/cmd/devp2p/internal/ethtest/suite.go
+++ b/cmd/devp2p/internal/ethtest/suite.go
@@ -17,79 +17,86 @@
package ethtest
import (
- "time"
+ "crypto/rand"
+ "math/big"
+ "reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/internal/utesting"
+ "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/holiman/uint256"
)
// Suite represents a structure used to test a node's conformance
// to the eth protocol.
type Suite struct {
- Dest *enode.Node
-
- chain *Chain
- fullChain *Chain
+ Dest *enode.Node
+ chain *Chain
+ engine *EngineClient
}
// NewSuite creates and returns a new eth-test suite that can
// be used to test the given node against the given blockchain
// data.
-func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, error) {
- chain, err := loadChain(chainfile, genesisfile)
+func NewSuite(dest *enode.Node, chainDir, engineURL, jwt string) (*Suite, error) {
+ chain, err := NewChain(chainDir)
+ if err != nil {
+ return nil, err
+ }
+ engine, err := NewEngineClient(chainDir, engineURL, jwt)
if err != nil {
return nil, err
}
return &Suite{
- Dest: dest,
- chain: chain.Shorten(1000),
- fullChain: chain,
+ Dest: dest,
+ chain: chain,
+ engine: engine,
}, nil
}
func (s *Suite) EthTests() []utesting.Test {
return []utesting.Test{
// status
- {Name: "TestStatus", Fn: s.TestStatus},
+ {Name: "Status", Fn: s.TestStatus},
// get block headers
- {Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
- {Name: "TestSimultaneousRequests", Fn: s.TestSimultaneousRequests},
- {Name: "TestSameRequestID", Fn: s.TestSameRequestID},
- {Name: "TestZeroRequestID", Fn: s.TestZeroRequestID},
+ {Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
+ {Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
+ {Name: "SameRequestID", Fn: s.TestSameRequestID},
+ {Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
// get block bodies
- {Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
- // broadcast
- {Name: "TestBroadcast", Fn: s.TestBroadcast},
- {Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
- {Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
- {Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
- // malicious handshakes + status
- {Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
- {Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
+ {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies},
+ // // malicious handshakes + status
+ {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake},
+ {Name: "MaliciousStatus", Fn: s.TestMaliciousStatus},
// test transactions
- {Name: "TestTransaction", Fn: s.TestTransaction},
- {Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
- {Name: "TestLargeTxRequest", Fn: s.TestLargeTxRequest},
- {Name: "TestNewPooledTxs", Fn: s.TestNewPooledTxs},
+ {Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true},
+ {Name: "Transaction", Fn: s.TestTransaction},
+ {Name: "InvalidTxs", Fn: s.TestInvalidTxs},
+ {Name: "NewPooledTxs", Fn: s.TestNewPooledTxs},
+ {Name: "BlobViolations", Fn: s.TestBlobViolations},
}
}
func (s *Suite) SnapTests() []utesting.Test {
return []utesting.Test{
- {Name: "TestSnapStatus", Fn: s.TestSnapStatus},
- {Name: "TestSnapAccountRange", Fn: s.TestSnapGetAccountRange},
- {Name: "TestSnapGetByteCodes", Fn: s.TestSnapGetByteCodes},
- {Name: "TestSnapGetTrieNodes", Fn: s.TestSnapTrieNodes},
- {Name: "TestSnapGetStorageRanges", Fn: s.TestSnapGetStorageRanges},
+ {Name: "Status", Fn: s.TestSnapStatus},
+ {Name: "AccountRange", Fn: s.TestSnapGetAccountRange},
+ {Name: "GetByteCodes", Fn: s.TestSnapGetByteCodes},
+ {Name: "GetTrieNodes", Fn: s.TestSnapTrieNodes},
+ {Name: "GetStorageRanges", Fn: s.TestSnapGetStorageRanges},
}
}
-// TestStatus attempts to connect to the given node and exchange
-// a status message with it on the eth protocol.
func (s *Suite) TestStatus(t *utesting.T) {
+ t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -102,9 +109,14 @@ func (s *Suite) TestStatus(t *utesting.T) {
}
}
-// TestGetBlockHeaders tests whether the given node can respond to
-// an eth `GetBlockHeaders` request and that the response is accurate.
+// headersMatch returns whether the received headers match the given request
+func headersMatch(expected []*types.Header, headers []*types.Header) bool {
+ return reflect.DeepEqual(expected, headers)
+}
+
func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
+ t.Log(`This test requests block headers from the node.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -115,8 +127,9 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // write request
- req := &GetBlockHeaders{
+ // Send headers request.
+ req := ð.GetBlockHeadersPacket{
+ RequestId: 33,
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
Amount: 2,
@@ -124,28 +137,31 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
Reverse: false,
},
}
-
- headers, err := conn.headersRequest(req, s.chain, 33)
- if err != nil {
- t.Fatalf("could not get block headers: %v", err)
+ // Read headers response.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
+ t.Fatalf("could not write to connection: %v", err)
}
- // check for correct headers
+ headers := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
+ t.Fatalf("error reading msg: %v", err)
+ }
+ if got, want := headers.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id")
+ }
+ // Check for correct headers.
expected, err := s.chain.GetHeaders(req)
if err != nil {
t.Fatalf("failed to get headers for given request: %v", err)
}
-
- if !headersMatch(expected, headers) {
+ if !headersMatch(expected, headers.BlockHeadersRequest) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
}
}
-// TestSimultaneousRequests sends two simultaneous `GetBlockHeader` requests from
-// the same connection with different request IDs and checks to make sure the node
-// responds with the correct headers per request.
-// nolint:typecheck
func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
- // create a connection
+ t.Log(`This test requests blocks headers from the node, performing two requests
+concurrently, with different request IDs.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -157,8 +173,8 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
t.Fatalf("peering failed: %v", err)
}
- // create two requests
- req1 := &GetBlockHeaders{
+ // Create two different requests.
+ req1 := ð.GetBlockHeadersPacket{
RequestId: uint64(111),
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
@@ -169,7 +185,7 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
Reverse: false,
},
}
- req2 := &GetBlockHeaders{
+ req2 := ð.GetBlockHeadersPacket{
RequestId: uint64(222),
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
@@ -181,52 +197,47 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
},
}
- // write the first request
- if err := conn.Write(req1); err != nil {
+ // Send both requests.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req1); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // write the second request
- if err := conn.Write(req2); err != nil {
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req2); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // wait for responses
- msg := conn.waitForResponse(s.chain, timeout, req1.RequestId)
- headers1, ok := msg.(*BlockHeaders)
-
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
+ // Wait for responses.
+ headers1 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
+ t.Fatalf("error reading block headers msg: %v", err)
+ }
+ if got, want := headers1.RequestId, req1.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
+ }
+ headers2 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
+ t.Fatalf("error reading block headers msg: %v", err)
+ }
+ if got, want := headers2.RequestId, req2.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
}
- msg = conn.waitForResponse(s.chain, timeout, req2.RequestId)
- headers2, ok := msg.(*BlockHeaders)
-
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
- }
-
- // check received headers for accuracy
- expected1, err := s.chain.GetHeaders(req1)
- if err != nil {
+ // Check received headers for accuracy.
+ if expected, err := s.chain.GetHeaders(req1); err != nil {
t.Fatalf("failed to get expected headers for request 1: %v", err)
+ } else if !headersMatch(expected, headers1.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
}
-
- expected2, err := s.chain.GetHeaders(req2)
- if err != nil {
+ if expected, err := s.chain.GetHeaders(req2); err != nil {
t.Fatalf("failed to get expected headers for request 2: %v", err)
- }
- if !headersMatch(expected1, headers1.BlockHeadersRequest) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
- }
- if !headersMatch(expected2, headers2.BlockHeadersRequest) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
+ } else if !headersMatch(expected, headers2.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
}
}
-// TestSameRequestID sends two requests with the same request ID to a
-// single node.
-// nolint:typecheck
func (s *Suite) TestSameRequestID(t *utesting.T) {
+ t.Log(`This test requests block headers, performing two concurrent requests with the
+same request ID. The node should handle the request by responding to both requests.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -237,9 +248,10 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create requests
+
+ // Create two different requests with the same ID.
reqID := uint64(1234)
- request1 := &GetBlockHeaders{
+ request1 := ð.GetBlockHeadersPacket{
RequestId: reqID,
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
@@ -248,7 +260,7 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
Amount: 2,
},
}
- request2 := &GetBlockHeaders{
+ request2 := ð.GetBlockHeadersPacket{
RequestId: reqID,
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
@@ -258,51 +270,47 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
},
}
- // write the requests
- if err = conn.Write(request1); err != nil {
+ // Send the requests.
+ if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request1); err != nil {
+ t.Fatalf("failed to write to connection: %v", err)
+ }
+ if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request2); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- if err = conn.Write(request2); err != nil {
- t.Fatalf("failed to write to connection: %v", err)
+ // Wait for the responses.
+ headers1 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ if got, want := headers1.RequestId, request1.RequestId; got != want {
+ t.Fatalf("unexpected request id: got %d, want %d", got, want)
+ }
+ headers2 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ if got, want := headers2.RequestId, request2.RequestId; got != want {
+ t.Fatalf("unexpected request id: got %d, want %d", got, want)
}
- // wait for responses
- msg := conn.waitForResponse(s.chain, timeout, reqID)
- headers1, ok := msg.(*BlockHeaders)
-
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
- }
-
- msg = conn.waitForResponse(s.chain, timeout, reqID)
- headers2, ok := msg.(*BlockHeaders)
-
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
- }
-
- // check if headers match
- expected1, err := s.chain.GetHeaders(request1)
- if err != nil {
+ // Check if headers match.
+ if expected, err := s.chain.GetHeaders(request1); err != nil {
t.Fatalf("failed to get expected block headers: %v", err)
+ } else if !headersMatch(expected, headers1.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
}
-
- expected2, err := s.chain.GetHeaders(request2)
- if err != nil {
+ if expected, err := s.chain.GetHeaders(request2); err != nil {
t.Fatalf("failed to get expected block headers: %v", err)
- }
- if !headersMatch(expected1, headers1.BlockHeadersRequest) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
- }
- if !headersMatch(expected2, headers2.BlockHeadersRequest) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
+ } else if !headersMatch(expected, headers2.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
}
}
-// TestZeroRequestID checks that a message with a request ID of zero is still handled
-// by the node.
func (s *Suite) TestZeroRequestID(t *utesting.T) {
+ t.Log(`This test sends a GetBlockHeaders message with a request-id of zero,
+and expects a response.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -313,32 +321,33 @@ func (s *Suite) TestZeroRequestID(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
-
- req := &GetBlockHeaders{
+ req := ð.GetBlockHeadersPacket{
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: 0},
Amount: 2,
},
}
-
- headers, err := conn.headersRequest(req, s.chain, 0)
- if err != nil {
- t.Fatalf("failed to get block headers: %v", err)
+ // Read headers response.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
+ t.Fatalf("could not write to connection: %v", err)
}
-
- expected, err := s.chain.GetHeaders(req)
- if err != nil {
+ headers := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
+ t.Fatalf("error reading msg: %v", err)
+ }
+ if got, want := headers.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id")
+ }
+ if expected, err := s.chain.GetHeaders(req); err != nil {
t.Fatalf("failed to get expected block headers: %v", err)
- }
-
- if !headersMatch(expected, headers) {
+ } else if !headersMatch(expected, headers.BlockHeadersRequest) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
}
}
-// TestGetBlockBodies tests whether the given node can respond to
-// a `GetBlockBodies` request and that the response is accurate.
func (s *Suite) TestGetBlockBodies(t *utesting.T) {
+ t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -349,160 +358,302 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create block bodies request
- req := &GetBlockBodies{
- RequestId: uint64(55),
+ // Create block bodies request.
+ req := ð.GetBlockBodiesPacket{
+ RequestId: 55,
GetBlockBodiesRequest: eth.GetBlockBodiesRequest{
s.chain.blocks[54].Hash(),
s.chain.blocks[75].Hash(),
},
}
- if err := conn.Write(req); err != nil {
+ if err := conn.Write(ethProto, eth.GetBlockBodiesMsg, req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
- // wait for block bodies response
- msg := conn.waitForResponse(s.chain, timeout, req.RequestId)
- resp, ok := msg.(*BlockBodies)
-
- if !ok {
- t.Fatalf("unexpected: %s", pretty.Sdump(msg))
+ // Wait for response.
+ resp := new(eth.BlockBodiesPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockBodiesMsg, &resp); err != nil {
+ t.Fatalf("error reading block bodies msg: %v", err)
+ }
+ if got, want := resp.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id in respond", got, want)
}
bodies := resp.BlockBodiesResponse
- t.Logf("received %d block bodies", len(bodies))
if len(bodies) != len(req.GetBlockBodiesRequest) {
- t.Fatalf("wrong bodies in response: expected %d bodies, "+
- "got %d", len(req.GetBlockBodiesRequest), len(bodies))
+ t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), len(bodies))
}
}
-// TestBroadcast tests whether a block announcement is correctly
-// propagated to the node's peers.
-func (s *Suite) TestBroadcast(t *utesting.T) {
- if err := s.sendNextBlock(); err != nil {
- t.Fatalf("block broadcast failed: %v", err)
- }
+// randBuf makes a random buffer size kilobytes large.
+func randBuf(size int) []byte {
+ buf := make([]byte, size*1024)
+ rand.Read(buf)
+ return buf
}
-// TestLargeAnnounce tests the announcement mechanism with a large block.
-func (s *Suite) TestLargeAnnounce(t *utesting.T) {
- nextBlock := len(s.chain.blocks)
- blocks := []*NewBlock{
+func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
+ t.Log(`This test tries to send malicious data during the devp2p handshake, in various ways.`)
+
+ // Write hello to client.
+ var (
+ key, _ = crypto.GenerateKey()
+ pub0 = crypto.FromECDSAPub(&key.PublicKey)[1:]
+ version = eth.ProtocolVersions[0]
+ )
+ handshakes := []*protoHandshake{
{
- Block: largeBlock(),
- TD: s.fullChain.TotalDifficultyAt(nextBlock),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: string(randBuf(2)), Version: version},
+ },
+ ID: pub0,
},
{
- Block: s.fullChain.blocks[nextBlock],
- TD: largeNumber(2),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: append(pub0, byte(0)),
},
{
- Block: largeBlock(),
- TD: largeNumber(2),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: append(pub0, pub0...),
+ },
+ {
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: randBuf(2),
+ },
+ {
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: string(randBuf(2)), Version: version},
+ },
+ ID: randBuf(2),
},
}
-
- for i, blockAnnouncement := range blocks[0:3] {
- t.Logf("Testing malicious announcement: %v\n", i)
-
- conn, err := s.dial()
+ for _, handshake := range handshakes {
+ conn, err := s.dialAs(key)
if err != nil {
t.Fatalf("dial failed: %v", err)
}
+ defer conn.Close()
- if err := conn.peer(s.chain, nil); err != nil {
- t.Fatalf("peering failed: %v", err)
- }
-
- if err := conn.Write(blockAnnouncement); err != nil {
+ if err := conn.Write(ethProto, handshakeMsg, handshake); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
- // Invalid announcement, check that peer disconnected
- switch msg := conn.readAndServe(s.chain, 8*time.Second).(type) {
- case *Disconnect:
- case *Error:
- break
- default:
- t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg))
+ // Check that the peer disconnected
+ for i := 0; i < 2; i++ {
+ code, _, err := conn.Read()
+ if err != nil {
+ // Client may have disconnected without sending disconnect msg.
+ continue
+ }
+ switch code {
+ case discMsg:
+ case handshakeMsg:
+ // Discard one hello as Hello's are sent concurrently
+ continue
+ default:
+ t.Fatalf("unexpected msg: code %d", code)
+ }
}
- conn.Close()
- }
- // Test the last block as a valid block
- if err := s.sendNextBlock(); err != nil {
- t.Fatalf("failed to broadcast next block: %v", err)
}
}
-// TestOldAnnounce tests the announcement mechanism with an old block.
-func (s *Suite) TestOldAnnounce(t *utesting.T) {
- if err := s.oldAnnounce(); err != nil {
- t.Fatal(err)
- }
-}
-
-// TestBlockHashAnnounce sends a new block hash announcement and expects
-// the node to perform a `GetBlockHeaders` request.
-func (s *Suite) TestBlockHashAnnounce(t *utesting.T) {
- if err := s.hashAnnounce(); err != nil {
- t.Fatalf("block hash announcement failed: %v", err)
- }
-}
-
-// TestMaliciousHandshake tries to send malicious data during the handshake.
-func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
- if err := s.maliciousHandshakes(t); err != nil {
- t.Fatal(err)
- }
-}
-
-// TestMaliciousStatus sends a status package with a large total difficulty.
func (s *Suite) TestMaliciousStatus(t *utesting.T) {
+ t.Log(`This test sends a malicious eth Status message to the node and expects a disconnect.`)
+
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
-
- if err := s.maliciousStatus(conn); err != nil {
- t.Fatal(err)
+ if err := conn.handshake(); err != nil {
+ t.Fatalf("handshake failed: %v", err)
+ }
+ // Create status with large total difficulty.
+ status := ð.StatusPacket{
+ ProtocolVersion: uint32(conn.negotiatedProtoVersion),
+ NetworkID: s.chain.config.ChainID.Uint64(),
+ TD: new(big.Int).SetBytes(randBuf(2048)),
+ Head: s.chain.Head().Hash(),
+ Genesis: s.chain.GetBlock(0).Hash(),
+ ForkID: s.chain.ForkID(),
+ }
+ if err := conn.statusExchange(s.chain, status); err != nil {
+ t.Fatalf("status exchange failed: %v", err)
+ }
+ // Wait for disconnect.
+ code, _, err := conn.Read()
+ if err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ switch code {
+ case discMsg:
+ break
+ default:
+ t.Fatalf("expected disconnect, got: %d", code)
}
}
-// TestTransaction sends a valid transaction to the node and
-// checks if the transaction gets propagated.
func (s *Suite) TestTransaction(t *utesting.T) {
- if err := s.sendSuccessfulTxs(t); err != nil {
- t.Fatal(err)
- }
-}
+ t.Log(`This test sends a valid transaction to the node and checks if the
+transaction gets propagated.`)
-// TestMaliciousTx sends several invalid transactions and tests whether
-// the node will propagate them.
-func (s *Suite) TestMaliciousTx(t *utesting.T) {
- if err := s.sendMaliciousTxs(t); err != nil {
- t.Fatal(err)
- }
-}
-
-// TestLargeTxRequest tests whether a node can fulfill a large GetPooledTransactions
-// request.
-// nolint:typecheck
-func (s *Suite) TestLargeTxRequest(t *utesting.T) {
- // send the next block to ensure the node is no longer syncing and
- // is able to accept txs
- if err := s.sendNextBlock(); err != nil {
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
t.Fatalf("failed to send next block: %v", err)
}
- // send 2000 transactions to the node
- hashMap, txs, err := generateTxs(s, 2000)
+ from, nonce := s.chain.GetSender(0)
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 30000,
+ To: &common.Address{0xaa},
+ Value: common.Big1,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
if err != nil {
- t.Fatalf("failed to generate transactions: %v", err)
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil {
+ t.Fatal(err)
+ }
+ s.chain.IncNonce(from, 1)
+}
+
+func (s *Suite) TestInvalidTxs(t *utesting.T) {
+ t.Log(`This test sends several kinds of invalid transactions and checks that the node
+does not propagate them.`)
+
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("failed to send next block: %v", err)
}
- if err = sendMultipleSuccessfulTxs(t, s, txs); err != nil {
- t.Fatalf("failed to send multiple txs: %v", err)
+ from, nonce := s.chain.GetSender(0)
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 30000,
+ To: &common.Address{0xaa},
}
- // set up connection to receive to ensure node is peered with the receiving connection
- // before tx request is sent
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil {
+ t.Fatalf("failed to send txs: %v", err)
+ }
+ s.chain.IncNonce(from, 1)
+
+ inners := []*types.DynamicFeeTx{
+ // Nonce already used
+ {
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce - 1,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 100000,
+ },
+ // Value exceeds balance
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 100000,
+ Value: s.chain.Balance(from),
+ },
+ // Gas limit too low
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 1337,
+ },
+ // Code size too large
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Data: randBuf(50),
+ Gas: 1_000_000,
+ },
+ // Data too large
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ To: &common.Address{0xaa},
+ Data: randBuf(128),
+ Gas: 5_000_000,
+ },
+ }
+
+ var txs []*types.Transaction
+ for _, inner := range inners {
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ txs = append(txs, tx)
+ }
+ if err := s.sendInvalidTxs(t, txs); err != nil {
+ t.Fatalf("failed to send invalid txs: %v", err)
+ }
+}
+
+func (s *Suite) TestLargeTxRequest(t *utesting.T) {
+ t.Log(`This test first send ~2000 transactions to the node, then requests them
+on another peer connection using GetPooledTransactions.`)
+
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("failed to send next block: %v", err)
+ }
+
+ // Generate many transactions to seed target with.
+ var (
+ from, nonce = s.chain.GetSender(1)
+ count = 2000
+ txs []*types.Transaction
+ hashes []common.Hash
+ set = make(map[common.Hash]struct{})
+ )
+ for i := 0; i < count; i++ {
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce + uint64(i),
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 75000,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: err")
+ }
+ txs = append(txs, tx)
+ set[tx.Hash()] = struct{}{}
+ hashes = append(hashes, tx.Hash())
+ }
+ s.chain.IncNonce(from, uint64(count))
+
+ // Send txs.
+ if err := s.sendTxs(t, txs); err != nil {
+ t.Fatalf("failed to send txs: %v", err)
+ }
+
+ // Set up receive connection to ensure node is peered with the receiving
+ // connection before tx request is sent.
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -513,59 +664,64 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create and send pooled tx request
- hashes := make([]common.Hash, 0)
- for _, hash := range hashMap {
- hashes = append(hashes, hash)
- }
-
- getTxReq := &GetPooledTransactions{
+ // Create and send pooled tx request.
+ req := ð.GetPooledTransactionsPacket{
RequestId: 1234,
GetPooledTransactionsRequest: hashes,
}
-
- if err = conn.Write(getTxReq); err != nil {
+ if err = conn.Write(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
t.Fatalf("could not write to conn: %v", err)
}
- // check that all received transactions match those that were sent to node
- switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) {
- case *PooledTransactions:
- for _, gotTx := range msg.PooledTransactionsResponse {
- if _, exists := hashMap[gotTx.Hash()]; !exists {
- t.Fatalf("unexpected tx received: %v", gotTx.Hash())
- }
+ // Check that all received transactions match those that were sent to node.
+ msg := new(eth.PooledTransactionsPacket)
+ if err := conn.ReadMsg(ethProto, eth.PooledTransactionsMsg, &msg); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ if got, want := msg.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
+ }
+ for _, got := range msg.PooledTransactionsResponse {
+ if _, exists := set[got.Hash()]; !exists {
+ t.Fatalf("unexpected tx received: %v", got.Hash())
}
- default:
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
}
}
-// TestNewPooledTxs tests whether a node will do a GetPooledTransactions
-// request upon receiving a NewPooledTransactionHashes announcement.
func (s *Suite) TestNewPooledTxs(t *utesting.T) {
- // send the next block to ensure the node is no longer syncing and
- // is able to accept txs
- if err := s.sendNextBlock(); err != nil {
+ t.Log(`This test announces transaction hashes to the node and expects it to fetch
+the transactions using a GetPooledTransactions request.`)
+
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
t.Fatalf("failed to send next block: %v", err)
}
- // generate 50 txs
- _, txs, err := generateTxs(s, 50)
- if err != nil {
- t.Fatalf("failed to generate transactions: %v", err)
- }
-
- hashes := make([]common.Hash, len(txs))
- types := make([]byte, len(txs))
- sizes := make([]uint32, len(txs))
-
- for i, tx := range txs {
+ var (
+ count = 50
+ from, nonce = s.chain.GetSender(1)
+ hashes = make([]common.Hash, count)
+ txTypes = make([]byte, count)
+ sizes = make([]uint32, count)
+ )
+ for i := 0; i < count; i++ {
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce + uint64(i),
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 75000,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: err")
+ }
hashes[i] = tx.Hash()
- types[i] = tx.Type()
+ txTypes[i] = tx.Type()
sizes[i] = uint32(tx.Size())
}
+ s.chain.IncNonce(from, uint64(count))
- // send announcement
+ // Connect to peer.
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -577,44 +733,141 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
t.Fatalf("peering failed: %v", err)
}
- var ann Message = NewPooledTransactionHashes{Types: types, Sizes: sizes, Hashes: hashes}
-
- if conn.negotiatedProtoVersion < eth.ETH68 {
- ann = NewPooledTransactionHashes66(hashes)
- }
-
- err = conn.Write(ann)
-
+ // Send announcement.
+ ann := eth.NewPooledTransactionHashesPacket{Types: txTypes, Sizes: sizes, Hashes: hashes}
+ err = conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann)
if err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // wait for GetPooledTxs request
+ // Wait for GetPooledTxs request.
for {
- msg := conn.readAndServe(s.chain, timeout)
+ msg, err := conn.ReadEth()
+ if err != nil {
+ t.Fatalf("failed to read eth msg: %v", err)
+ }
switch msg := msg.(type) {
- case *GetPooledTransactions:
+ case *eth.GetPooledTransactionsPacket:
if len(msg.GetPooledTransactionsRequest) != len(hashes) {
t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest))
}
return
-
- // ignore propagated txs from previous tests
- case *NewPooledTransactionHashes66:
+ case *eth.NewPooledTransactionHashesPacket:
continue
- case *NewPooledTransactionHashes:
- continue
- case *Transactions:
- continue
-
- // ignore block announcements from previous tests
- case *NewBlockHashes:
- continue
- case *NewBlock:
+ case *eth.TransactionsPacket:
continue
default:
t.Fatalf("unexpected %s", pretty.Sdump(msg))
}
}
}
+
+func makeSidecar(data ...byte) *types.BlobTxSidecar {
+ var (
+ blobs = make([]kzg4844.Blob, len(data))
+ commitments []kzg4844.Commitment
+ proofs []kzg4844.Proof
+ )
+ for i := range blobs {
+ blobs[i][0] = data[i]
+ c, _ := kzg4844.BlobToCommitment(blobs[i])
+ p, _ := kzg4844.ComputeBlobProof(blobs[i], c)
+ commitments = append(commitments, c)
+ proofs = append(proofs, p)
+ }
+ return &types.BlobTxSidecar{
+ Blobs: blobs,
+ Commitments: commitments,
+ Proofs: proofs,
+ }
+}
+
+func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
+ from, nonce := s.chain.GetSender(5)
+ for i := 0; i < count; i++ {
+ // Make blob data, max of 2 blobs per tx.
+ blobdata := make([]byte, blobs%3)
+ for i := range blobdata {
+ blobdata[i] = discriminator
+ blobs -= 1
+ }
+ inner := &types.BlobTx{
+ ChainID: uint256.MustFromBig(s.chain.config.ChainID),
+ Nonce: nonce + uint64(i),
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
+ Gas: 100000,
+ BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
+ BlobHashes: makeSidecar(blobdata...).BlobHashes(),
+ Sidecar: makeSidecar(blobdata...),
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ panic("blob tx signing failed")
+ }
+ txs = append(txs, tx)
+ }
+ return txs
+}
+
+func (s *Suite) TestBlobViolations(t *utesting.T) {
+ t.Log(`This test sends some invalid blob tx announcements and expects the node to disconnect.`)
+
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("send fcu failed: %v", err)
+ }
+ // Create blob txs for each tests with unique tx hashes.
+ var (
+ t1 = s.makeBlobTxs(2, 3, 0x1)
+ t2 = s.makeBlobTxs(2, 3, 0x2)
+ )
+ for _, test := range []struct {
+ ann eth.NewPooledTransactionHashesPacket
+ resp eth.PooledTransactionsResponse
+ }{
+ // Invalid tx size.
+ {
+ ann: eth.NewPooledTransactionHashesPacket{
+ Types: []byte{types.BlobTxType, types.BlobTxType},
+ Sizes: []uint32{uint32(t1[0].Size()), uint32(t1[1].Size() + 10)},
+ Hashes: []common.Hash{t1[0].Hash(), t1[1].Hash()},
+ },
+ resp: eth.PooledTransactionsResponse(t1),
+ },
+ // Wrong tx type.
+ {
+ ann: eth.NewPooledTransactionHashesPacket{
+ Types: []byte{types.DynamicFeeTxType, types.BlobTxType},
+ Sizes: []uint32{uint32(t2[0].Size()), uint32(t2[1].Size())},
+ Hashes: []common.Hash{t2[0].Hash(), t2[1].Hash()},
+ },
+ resp: eth.PooledTransactionsResponse(t2),
+ },
+ } {
+ conn, err := s.dial()
+ if err != nil {
+ t.Fatalf("dial fail: %v", err)
+ }
+ if err := conn.peer(s.chain, nil); err != nil {
+ t.Fatalf("peering failed: %v", err)
+ }
+ if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, test.ann); err != nil {
+ t.Fatalf("sending announcement failed: %v", err)
+ }
+ req := new(eth.GetPooledTransactionsPacket)
+ if err := conn.ReadMsg(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
+ t.Fatalf("reading pooled tx request failed: %v", err)
+ }
+ resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: test.resp}
+ if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
+ t.Fatalf("writing pooled tx response failed: %v", err)
+ }
+ if code, _, err := conn.Read(); err != nil {
+ t.Fatalf("expected disconnect on blob violation, got err: %v", err)
+ } else if code != discMsg {
+ t.Fatalf("expected disconnect on blob violation, got msg code: %d", code)
+ }
+ conn.Close()
+ }
+}
diff --git a/cmd/devp2p/internal/ethtest/suite_test.go b/cmd/devp2p/internal/ethtest/suite_test.go
index 25ac38055b..4bd062e02f 100644
--- a/cmd/devp2p/internal/ethtest/suite_test.go
+++ b/cmd/devp2p/internal/ethtest/suite_test.go
@@ -17,32 +17,47 @@
package ethtest
import (
+ crand "crypto/rand"
+ "fmt"
"os"
+ "path"
"testing"
"time"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
)
-var (
- genesisFile = "./testdata/genesis.json"
- halfchainFile = "./testdata/halfchain.rlp"
- fullchainFile = "./testdata/chain.rlp"
-)
+func makeJWTSecret() (string, [32]byte, error) {
+ var secret [32]byte
+ if _, err := crand.Read(secret[:]); err != nil {
+ return "", secret, fmt.Errorf("failed to create jwt secret: %v", err)
+ }
+ jwtPath := path.Join(os.TempDir(), "jwt_secret")
+ if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
+ return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err)
+ }
+ return jwtPath, secret, nil
+}
func TestEthSuite(t *testing.T) {
- t.Parallel()
- geth, err := runGeth()
+ jwtPath, secret, err := makeJWTSecret()
+ if err != nil {
+ t.Fatalf("could not make jwt secret: %v", err)
+ }
+ geth, err := runGeth("./testdata", jwtPath)
if err != nil {
t.Fatalf("could not run geth: %v", err)
}
defer geth.Close()
- suite, err := NewSuite(geth.Server().Self(), fullchainFile, genesisFile)
+ suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:]))
if err != nil {
t.Fatalf("could not create new test suite: %v", err)
}
@@ -52,7 +67,10 @@ func TestEthSuite(t *testing.T) {
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
- result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
+ if test.Slow && testing.Short() {
+ t.Skipf("%s: skipping in -short mode", test.Name)
+ }
+ result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed {
t.Fatal()
}
@@ -61,21 +79,24 @@ func TestEthSuite(t *testing.T) {
}
func TestSnapSuite(t *testing.T) {
- t.Parallel()
- geth, err := runGeth()
+ jwtPath, secret, err := makeJWTSecret()
+ if err != nil {
+ t.Fatalf("could not make jwt secret: %v", err)
+ }
+ geth, err := runGeth("./testdata", jwtPath)
if err != nil {
t.Fatalf("could not run geth: %v", err)
}
defer geth.Close()
- suite, err := NewSuite(geth.Server().Self(), fullchainFile, genesisFile)
+ suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:]))
if err != nil {
t.Fatalf("could not create new test suite: %v", err)
}
for _, test := range suite.SnapTests() {
t.Run(test.Name, func(t *testing.T) {
- result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
+ result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed {
t.Fatal()
}
@@ -84,20 +105,23 @@ func TestSnapSuite(t *testing.T) {
}
// runGeth creates and starts a geth node
-func runGeth() (*node.Node, error) {
+func runGeth(dir string, jwtPath string) (*node.Node, error) {
stack, err := node.New(&node.Config{
+ AuthAddr: "127.0.0.1",
+ AuthPort: 0,
P2P: p2p.Config{
ListenAddr: "127.0.0.1:0",
NoDiscovery: true,
MaxPeers: 10, // in case a test requires multiple connections, can be changed in the future
NoDial: true,
},
+ JWTSecret: jwtPath,
})
if err != nil {
return nil, err
}
- err = setupGeth(stack)
+ err = setupGeth(stack, dir)
if err != nil {
stack.Close()
return nil, err
@@ -111,12 +135,11 @@ func runGeth() (*node.Node, error) {
return stack, nil
}
-func setupGeth(stack *node.Node) error {
- chain, err := loadChain(halfchainFile, genesisFile)
+func setupGeth(stack *node.Node, dir string) error {
+ chain, err := NewChain(dir)
if err != nil {
return err
}
-
backend, err := eth.New(stack, ðconfig.Config{
Genesis: &chain.genesis,
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
@@ -129,8 +152,9 @@ func setupGeth(stack *node.Node) error {
if err != nil {
return err
}
- backend.SetSynced()
-
+ if err := catalyst.Register(stack, backend); err != nil {
+ return fmt.Errorf("failed to register catalyst service: %v", err)
+ }
_, err = backend.BlockChain().InsertChain(chain.blocks[1:])
return err
diff --git a/cmd/devp2p/internal/ethtest/testdata/accounts.json b/cmd/devp2p/internal/ethtest/testdata/accounts.json
new file mode 100644
index 0000000000..c9666235a8
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/accounts.json
@@ -0,0 +1,62 @@
+{
+ "0x0c2c51a0990aee1d73c1228de158688341557508": {
+ "key": "0xbfcd0e032489319f4e5ca03e643b2025db624be6cf99cbfed90c4502e3754850"
+ },
+ "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "key": "0x457075f6822ac29481154792f65c5f1ec335b4fea9ca20f3fea8fa1d78a12c68"
+ },
+ "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "key": "0x865898edcf43206d138c93f1bbd86311f4657b057658558888aa5ac4309626a6"
+ },
+ "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "key": "0xee7f7875d826d7443ccc5c174e38b2c436095018774248a8074ee92d8914dcdb"
+ },
+ "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "key": "0x25e6ce8611cefb5cd338aeaa9292ed2139714668d123a4fb156cabb42051b5b7"
+ },
+ "0x2d389075be5be9f2246ad654ce152cf05990b209": {
+ "key": "0x19168cd7767604b3d19b99dc3da1302b9ccb6ee9ad61660859e07acd4a2625dd"
+ },
+ "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "key": "0x71aa7d299c7607dabfc3d0e5213d612b5e4a97455b596c2f642daac43fa5eeaa"
+ },
+ "0x4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "key": "0x47f666f20e2175606355acec0ea1b37870c15e5797e962340da7ad7972a537e8"
+ },
+ "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "key": "0xa88293fefc623644969e2ce6919fb0dbd0fd64f640293b4bf7e1a81c97e7fc7f"
+ },
+ "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "key": "0x6e1e16a9c15641c73bf6e237f9293ab1d4e7c12b9adf83cfc94bcf969670f72d"
+ },
+ "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "key": "0x41be4e00aac79f7ffbb3455053ec05e971645440d594c047cdcc56a3c7458bd6"
+ },
+ "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "key": "0xc825f31cd8792851e33a290b3d749e553983111fc1f36dfbbdb45f101973f6a9"
+ },
+ "0x717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "key": "0x8d0faa04ae0f9bc3cd4c890aa025d5f40916f4729538b19471c0beefe11d9e19"
+ },
+ "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "key": "0x4552dbe6ca4699322b5d923d0c9bcdd24644f5db8bf89a085b67c6c49b8a1b91"
+ },
+ "0x83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "key": "0x34391cbbf06956bb506f45ec179cdd84df526aa364e27bbde65db9c15d866d00"
+ },
+ "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "key": "0xf6a8f1603b8368f3ca373292b7310c53bec7b508aecacd442554ebc1c5d0c856"
+ },
+ "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "key": "0x8d56bcbcf2c1b7109e1396a28d7a0234e33544ade74ea32c460ce4a443b239b1"
+ },
+ "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "key": "0xfc39d1c9ddbba176d806ebb42d7460189fe56ca163ad3eb6143bfc6beb6f6f72"
+ },
+ "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "key": "0x9ee3fd550664b246ad7cdba07162dd25530a3b1d51476dd1d85bbc29f0592684"
+ },
+ "0xeda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "key": "0x14cdde09d1640eb8c3cda063891b0453073f57719583381ff78811efa6d4199f"
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/chain.rlp b/cmd/devp2p/internal/ethtest/testdata/chain.rlp
index 5ebc2f3bb7..2964c02bb1 100644
Binary files a/cmd/devp2p/internal/ethtest/testdata/chain.rlp and b/cmd/devp2p/internal/ethtest/testdata/chain.rlp differ
diff --git a/cmd/devp2p/internal/ethtest/testdata/forkenv.json b/cmd/devp2p/internal/ethtest/testdata/forkenv.json
new file mode 100644
index 0000000000..86c49e2b97
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/forkenv.json
@@ -0,0 +1,20 @@
+{
+ "HIVE_CANCUN_TIMESTAMP": "840",
+ "HIVE_CHAIN_ID": "3503995874084926",
+ "HIVE_FORK_ARROW_GLACIER": "60",
+ "HIVE_FORK_BERLIN": "48",
+ "HIVE_FORK_BYZANTIUM": "18",
+ "HIVE_FORK_CONSTANTINOPLE": "24",
+ "HIVE_FORK_GRAY_GLACIER": "66",
+ "HIVE_FORK_HOMESTEAD": "0",
+ "HIVE_FORK_ISTANBUL": "36",
+ "HIVE_FORK_LONDON": "54",
+ "HIVE_FORK_MUIR_GLACIER": "42",
+ "HIVE_FORK_PETERSBURG": "30",
+ "HIVE_FORK_SPURIOUS": "12",
+ "HIVE_FORK_TANGERINE": "6",
+ "HIVE_MERGE_BLOCK_ID": "72",
+ "HIVE_NETWORK_ID": "3503995874084926",
+ "HIVE_SHANGHAI_TIMESTAMP": "780",
+ "HIVE_TERMINAL_TOTAL_DIFFICULTY": "9454784"
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/genesis.json b/cmd/devp2p/internal/ethtest/testdata/genesis.json
index b4de6e85a5..e8bb66bb3c 100644
--- a/cmd/devp2p/internal/ethtest/testdata/genesis.json
+++ b/cmd/devp2p/internal/ethtest/testdata/genesis.json
@@ -1,27 +1,112 @@
{
- "config": {
- "chainId": 19763,
- "homesteadBlock": 0,
- "eip150Block": 0,
- "eip155Block": 0,
- "eip158Block": 0,
- "byzantiumBlock": 0,
- "terminalTotalDifficultyPassed": true,
- "ethash": {}
+ "config": {
+ "chainId": 3503995874084926,
+ "homesteadBlock": 0,
+ "eip150Block": 6,
+ "eip155Block": 12,
+ "eip158Block": 12,
+ "byzantiumBlock": 18,
+ "constantinopleBlock": 24,
+ "petersburgBlock": 30,
+ "istanbulBlock": 36,
+ "muirGlacierBlock": 42,
+ "berlinBlock": 48,
+ "londonBlock": 54,
+ "arrowGlacierBlock": 60,
+ "grayGlacierBlock": 66,
+ "mergeNetsplitBlock": 72,
+ "shanghaiTime": 780,
+ "cancunTime": 840,
+ "terminalTotalDifficulty": 9454784,
+ "terminalTotalDifficultyPassed": true,
+ "ethash": {}
+ },
+ "nonce": "0x0",
+ "timestamp": "0x0",
+ "extraData": "0x68697665636861696e",
+ "gasLimit": "0x23f3e20",
+ "difficulty": "0x20000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase": "0x0000000000000000000000000000000000000000",
+ "alloc": {
+ "000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
+ "balance": "0x2a"
},
- "nonce": "0xdeadbeefdeadbeef",
- "timestamp": "0x0",
- "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "gasLimit": "0x80000000",
- "difficulty": "0x20000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "coinbase": "0x0000000000000000000000000000000000000000",
- "alloc": {
- "71562b71999873db5b286df957af199ec94617f7": {
- "balance": "0xffffffffffffffffffffffffff"
- }
+ "0c2c51a0990aee1d73c1228de158688341557508": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
},
- "number": "0x0",
- "gasUsed": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
-}
+ "14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "2d389075be5be9f2246ad654ce152cf05990b209": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000003"
+ },
+ "balance": "0x1",
+ "nonce": "0x1"
+ },
+ "c7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "d803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "e7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "eda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ }
+ },
+ "number": "0x0",
+ "gasUsed": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "baseFeePerGas": null,
+ "excessBlobGas": null,
+ "blobGasUsed": null
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp b/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp
deleted file mode 100644
index 1a820734e1..0000000000
Binary files a/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp and /dev/null differ
diff --git a/cmd/devp2p/internal/ethtest/testdata/headblock.json b/cmd/devp2p/internal/ethtest/testdata/headblock.json
new file mode 100644
index 0000000000..e84e96b0f0
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headblock.json
@@ -0,0 +1,23 @@
+{
+ "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "transactionsRoot": "0xecda39025fc4c609ce778d75eed0aa53b65ce1e3d1373b34bad8578cc31e5b48",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "difficulty": "0x0",
+ "number": "0x1f4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1388",
+ "extraData": "0x",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "baseFeePerGas": "0x7",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0",
+ "parentBeaconBlockRoot": "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c",
+ "hash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7"
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/headfcu.json b/cmd/devp2p/internal/ethtest/testdata/headfcu.json
new file mode 100644
index 0000000000..920212d0c0
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headfcu.json
@@ -0,0 +1,13 @@
+{
+ "jsonrpc": "2.0",
+ "id": "fcu500",
+ "method": "engine_forkchoiceUpdatedV3",
+ "params": [
+ {
+ "headBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "safeBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "finalizedBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7"
+ },
+ null
+ ]
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/headstate.json b/cmd/devp2p/internal/ethtest/testdata/headstate.json
new file mode 100644
index 0000000000..f7b076af69
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headstate.json
@@ -0,0 +1,4204 @@
+{
+ "root": "ea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "accounts": {
+ "0x0000000000000000000000000000000000000000": {
+ "balance": "233437500000029008737",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"
+ },
+ "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "balance": "42",
+ "nonce": 0,
+ "root": "0xac3162a8b9dbb4318b84219f3140e7a9ec35126234120297dde10f51b25f6a26",
+ "codeHash": "0xf57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c",
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000348": "0348",
+ "0x0000000000000000000000000000000000000000000000000000000000000352": "0352",
+ "0x000000000000000000000000000000000000000000000000000000000000035c": "035c",
+ "0x0000000000000000000000000000000000000000000000000000000000000366": "0366",
+ "0x0000000000000000000000000000000000000000000000000000000000000370": "0370",
+ "0x000000000000000000000000000000000000000000000000000000000000037a": "037a",
+ "0x0000000000000000000000000000000000000000000000000000000000000384": "0384",
+ "0x000000000000000000000000000000000000000000000000000000000000038e": "038e",
+ "0x0000000000000000000000000000000000000000000000000000000000000398": "0398",
+ "0x00000000000000000000000000000000000000000000000000000000000003a2": "03a2",
+ "0x00000000000000000000000000000000000000000000000000000000000003ac": "03ac",
+ "0x00000000000000000000000000000000000000000000000000000000000003b6": "03b6",
+ "0x00000000000000000000000000000000000000000000000000000000000003c0": "03c0",
+ "0x00000000000000000000000000000000000000000000000000000000000003ca": "03ca",
+ "0x00000000000000000000000000000000000000000000000000000000000003d4": "03d4",
+ "0x00000000000000000000000000000000000000000000000000000000000003de": "03de",
+ "0x00000000000000000000000000000000000000000000000000000000000003e8": "03e8",
+ "0x00000000000000000000000000000000000000000000000000000000000003f2": "03f2",
+ "0x00000000000000000000000000000000000000000000000000000000000003fc": "03fc",
+ "0x0000000000000000000000000000000000000000000000000000000000000406": "0406",
+ "0x0000000000000000000000000000000000000000000000000000000000000410": "0410",
+ "0x000000000000000000000000000000000000000000000000000000000000041a": "041a",
+ "0x0000000000000000000000000000000000000000000000000000000000000424": "0424",
+ "0x000000000000000000000000000000000000000000000000000000000000042e": "042e",
+ "0x0000000000000000000000000000000000000000000000000000000000000438": "0438",
+ "0x0000000000000000000000000000000000000000000000000000000000000442": "0442",
+ "0x000000000000000000000000000000000000000000000000000000000000044c": "044c",
+ "0x0000000000000000000000000000000000000000000000000000000000000456": "0456",
+ "0x0000000000000000000000000000000000000000000000000000000000000460": "0460",
+ "0x000000000000000000000000000000000000000000000000000000000000046a": "046a",
+ "0x0000000000000000000000000000000000000000000000000000000000000474": "0474",
+ "0x000000000000000000000000000000000000000000000000000000000000047e": "047e",
+ "0x0000000000000000000000000000000000000000000000000000000000000488": "0488",
+ "0x0000000000000000000000000000000000000000000000000000000000000492": "0492",
+ "0x000000000000000000000000000000000000000000000000000000000000049c": "049c",
+ "0x00000000000000000000000000000000000000000000000000000000000004a6": "04a6",
+ "0x00000000000000000000000000000000000000000000000000000000000004b0": "04b0",
+ "0x00000000000000000000000000000000000000000000000000000000000004ba": "04ba",
+ "0x00000000000000000000000000000000000000000000000000000000000004c4": "04c4",
+ "0x00000000000000000000000000000000000000000000000000000000000004ce": "04ce",
+ "0x00000000000000000000000000000000000000000000000000000000000004d8": "04d8",
+ "0x00000000000000000000000000000000000000000000000000000000000004e2": "04e2",
+ "0x00000000000000000000000000000000000000000000000000000000000004ec": "04ec",
+ "0x00000000000000000000000000000000000000000000000000000000000004f6": "04f6",
+ "0x0000000000000000000000000000000000000000000000000000000000000500": "0500",
+ "0x000000000000000000000000000000000000000000000000000000000000050a": "050a",
+ "0x0000000000000000000000000000000000000000000000000000000000000514": "0514",
+ "0x000000000000000000000000000000000000000000000000000000000000051e": "051e",
+ "0x0000000000000000000000000000000000000000000000000000000000000528": "0528",
+ "0x0000000000000000000000000000000000000000000000000000000000000532": "0532",
+ "0x000000000000000000000000000000000000000000000000000000000000053c": "053c",
+ "0x0000000000000000000000000000000000000000000000000000000000000546": "0546",
+ "0x0000000000000000000000000000000000000000000000000000000000000550": "0550",
+ "0x000000000000000000000000000000000000000000000000000000000000055a": "055a",
+ "0x0000000000000000000000000000000000000000000000000000000000000564": "0564",
+ "0x000000000000000000000000000000000000000000000000000000000000056e": "056e",
+ "0x0000000000000000000000000000000000000000000000000000000000000578": "0578",
+ "0x0000000000000000000000000000000000000000000000000000000000000582": "0582",
+ "0x000000000000000000000000000000000000000000000000000000000000058c": "058c",
+ "0x0000000000000000000000000000000000000000000000000000000000000596": "0596",
+ "0x00000000000000000000000000000000000000000000000000000000000005a0": "05a0",
+ "0x00000000000000000000000000000000000000000000000000000000000005aa": "05aa",
+ "0x00000000000000000000000000000000000000000000000000000000000005b4": "05b4",
+ "0x00000000000000000000000000000000000000000000000000000000000005be": "05be",
+ "0x00000000000000000000000000000000000000000000000000000000000005c8": "05c8",
+ "0x00000000000000000000000000000000000000000000000000000000000005d2": "05d2",
+ "0x00000000000000000000000000000000000000000000000000000000000005dc": "05dc",
+ "0x00000000000000000000000000000000000000000000000000000000000005e6": "05e6",
+ "0x00000000000000000000000000000000000000000000000000000000000005f0": "05f0",
+ "0x00000000000000000000000000000000000000000000000000000000000005fa": "05fa",
+ "0x0000000000000000000000000000000000000000000000000000000000000604": "0604",
+ "0x000000000000000000000000000000000000000000000000000000000000060e": "060e",
+ "0x0000000000000000000000000000000000000000000000000000000000000618": "0618",
+ "0x0000000000000000000000000000000000000000000000000000000000000622": "0622",
+ "0x000000000000000000000000000000000000000000000000000000000000062c": "062c",
+ "0x0000000000000000000000000000000000000000000000000000000000000636": "0636",
+ "0x0000000000000000000000000000000000000000000000000000000000000640": "0640",
+ "0x000000000000000000000000000000000000000000000000000000000000064a": "064a",
+ "0x0000000000000000000000000000000000000000000000000000000000000654": "0654",
+ "0x000000000000000000000000000000000000000000000000000000000000065e": "065e",
+ "0x0000000000000000000000000000000000000000000000000000000000000668": "0668",
+ "0x0000000000000000000000000000000000000000000000000000000000000672": "0672",
+ "0x000000000000000000000000000000000000000000000000000000000000067c": "067c",
+ "0x0000000000000000000000000000000000000000000000000000000000000686": "0686",
+ "0x0000000000000000000000000000000000000000000000000000000000000690": "0690",
+ "0x000000000000000000000000000000000000000000000000000000000000069a": "069a",
+ "0x00000000000000000000000000000000000000000000000000000000000006a4": "06a4",
+ "0x00000000000000000000000000000000000000000000000000000000000006ae": "06ae",
+ "0x00000000000000000000000000000000000000000000000000000000000006b8": "06b8",
+ "0x00000000000000000000000000000000000000000000000000000000000006c2": "06c2",
+ "0x00000000000000000000000000000000000000000000000000000000000006cc": "06cc",
+ "0x00000000000000000000000000000000000000000000000000000000000006d6": "06d6",
+ "0x00000000000000000000000000000000000000000000000000000000000006e0": "06e0",
+ "0x00000000000000000000000000000000000000000000000000000000000006ea": "06ea",
+ "0x00000000000000000000000000000000000000000000000000000000000006f4": "06f4",
+ "0x00000000000000000000000000000000000000000000000000000000000006fe": "06fe",
+ "0x0000000000000000000000000000000000000000000000000000000000000708": "0708",
+ "0x0000000000000000000000000000000000000000000000000000000000000712": "0712",
+ "0x000000000000000000000000000000000000000000000000000000000000071c": "071c",
+ "0x0000000000000000000000000000000000000000000000000000000000000726": "0726",
+ "0x0000000000000000000000000000000000000000000000000000000000000730": "0730",
+ "0x000000000000000000000000000000000000000000000000000000000000073a": "073a",
+ "0x0000000000000000000000000000000000000000000000000000000000000744": "0744",
+ "0x000000000000000000000000000000000000000000000000000000000000074e": "074e",
+ "0x0000000000000000000000000000000000000000000000000000000000000758": "0758",
+ "0x0000000000000000000000000000000000000000000000000000000000000762": "0762",
+ "0x000000000000000000000000000000000000000000000000000000000000076c": "076c",
+ "0x0000000000000000000000000000000000000000000000000000000000000776": "0776",
+ "0x0000000000000000000000000000000000000000000000000000000000000780": "0780",
+ "0x000000000000000000000000000000000000000000000000000000000000078a": "078a",
+ "0x0000000000000000000000000000000000000000000000000000000000000794": "0794",
+ "0x000000000000000000000000000000000000000000000000000000000000079e": "079e",
+ "0x00000000000000000000000000000000000000000000000000000000000007a8": "07a8",
+ "0x00000000000000000000000000000000000000000000000000000000000007b2": "07b2",
+ "0x00000000000000000000000000000000000000000000000000000000000007bc": "07bc",
+ "0x00000000000000000000000000000000000000000000000000000000000007c6": "07c6",
+ "0x00000000000000000000000000000000000000000000000000000000000007d0": "07d0",
+ "0x00000000000000000000000000000000000000000000000000000000000007da": "07da",
+ "0x00000000000000000000000000000000000000000000000000000000000007e4": "07e4",
+ "0x00000000000000000000000000000000000000000000000000000000000007ee": "07ee",
+ "0x00000000000000000000000000000000000000000000000000000000000007f8": "07f8",
+ "0x0000000000000000000000000000000000000000000000000000000000000802": "0802",
+ "0x000000000000000000000000000000000000000000000000000000000000080c": "080c",
+ "0x0000000000000000000000000000000000000000000000000000000000000816": "0816",
+ "0x0000000000000000000000000000000000000000000000000000000000000820": "0820",
+ "0x000000000000000000000000000000000000000000000000000000000000082a": "082a",
+ "0x0000000000000000000000000000000000000000000000000000000000000834": "0834",
+ "0x000000000000000000000000000000000000000000000000000000000000083e": "083e",
+ "0x0000000000000000000000000000000000000000000000000000000000000848": "0848",
+ "0x0000000000000000000000000000000000000000000000000000000000000852": "0852",
+ "0x000000000000000000000000000000000000000000000000000000000000085c": "085c",
+ "0x0000000000000000000000000000000000000000000000000000000000000866": "0866",
+ "0x0000000000000000000000000000000000000000000000000000000000000870": "0870",
+ "0x000000000000000000000000000000000000000000000000000000000000087a": "087a",
+ "0x0000000000000000000000000000000000000000000000000000000000000884": "0884",
+ "0x000000000000000000000000000000000000000000000000000000000000088e": "088e",
+ "0x0000000000000000000000000000000000000000000000000000000000000898": "0898",
+ "0x00000000000000000000000000000000000000000000000000000000000008a2": "08a2",
+ "0x00000000000000000000000000000000000000000000000000000000000008ac": "08ac",
+ "0x00000000000000000000000000000000000000000000000000000000000008b6": "08b6",
+ "0x00000000000000000000000000000000000000000000000000000000000008c0": "08c0",
+ "0x00000000000000000000000000000000000000000000000000000000000008ca": "08ca",
+ "0x00000000000000000000000000000000000000000000000000000000000008d4": "08d4",
+ "0x00000000000000000000000000000000000000000000000000000000000008de": "08de",
+ "0x00000000000000000000000000000000000000000000000000000000000008e8": "08e8",
+ "0x00000000000000000000000000000000000000000000000000000000000008f2": "08f2",
+ "0x00000000000000000000000000000000000000000000000000000000000008fc": "08fc",
+ "0x0000000000000000000000000000000000000000000000000000000000000906": "0906",
+ "0x0000000000000000000000000000000000000000000000000000000000000910": "0910",
+ "0x000000000000000000000000000000000000000000000000000000000000091a": "091a",
+ "0x0000000000000000000000000000000000000000000000000000000000000924": "0924",
+ "0x000000000000000000000000000000000000000000000000000000000000092e": "092e",
+ "0x0000000000000000000000000000000000000000000000000000000000000938": "0938",
+ "0x0000000000000000000000000000000000000000000000000000000000000942": "0942",
+ "0x000000000000000000000000000000000000000000000000000000000000094c": "094c",
+ "0x0000000000000000000000000000000000000000000000000000000000000956": "0956",
+ "0x0000000000000000000000000000000000000000000000000000000000000960": "0960",
+ "0x000000000000000000000000000000000000000000000000000000000000096a": "096a",
+ "0x0000000000000000000000000000000000000000000000000000000000000974": "0974",
+ "0x000000000000000000000000000000000000000000000000000000000000097e": "097e",
+ "0x0000000000000000000000000000000000000000000000000000000000000988": "0988",
+ "0x0000000000000000000000000000000000000000000000000000000000000992": "0992",
+ "0x000000000000000000000000000000000000000000000000000000000000099c": "099c",
+ "0x00000000000000000000000000000000000000000000000000000000000009a6": "09a6",
+ "0x00000000000000000000000000000000000000000000000000000000000009b0": "09b0",
+ "0x00000000000000000000000000000000000000000000000000000000000009ba": "09ba",
+ "0x00000000000000000000000000000000000000000000000000000000000009c4": "09c4",
+ "0x00000000000000000000000000000000000000000000000000000000000009ce": "09ce",
+ "0x00000000000000000000000000000000000000000000000000000000000009d8": "09d8",
+ "0x00000000000000000000000000000000000000000000000000000000000009e2": "09e2",
+ "0x00000000000000000000000000000000000000000000000000000000000009ec": "09ec",
+ "0x00000000000000000000000000000000000000000000000000000000000009f6": "09f6",
+ "0x0000000000000000000000000000000000000000000000000000000000000a00": "0a00",
+ "0x0000000000000000000000000000000000000000000000000000000000000a0a": "0a0a",
+ "0x0000000000000000000000000000000000000000000000000000000000000a14": "0a14",
+ "0x0000000000000000000000000000000000000000000000000000000000000a1e": "0a1e",
+ "0x0000000000000000000000000000000000000000000000000000000000000a28": "0a28",
+ "0x0000000000000000000000000000000000000000000000000000000000000a32": "0a32",
+ "0x0000000000000000000000000000000000000000000000000000000000000a3c": "0a3c",
+ "0x0000000000000000000000000000000000000000000000000000000000000a46": "0a46",
+ "0x0000000000000000000000000000000000000000000000000000000000000a50": "0a50",
+ "0x0000000000000000000000000000000000000000000000000000000000000a5a": "0a5a",
+ "0x0000000000000000000000000000000000000000000000000000000000000a64": "0a64",
+ "0x0000000000000000000000000000000000000000000000000000000000000a6e": "0a6e",
+ "0x0000000000000000000000000000000000000000000000000000000000000a78": "0a78",
+ "0x0000000000000000000000000000000000000000000000000000000000000a82": "0a82",
+ "0x0000000000000000000000000000000000000000000000000000000000000a8c": "0a8c",
+ "0x0000000000000000000000000000000000000000000000000000000000000a96": "0a96",
+ "0x0000000000000000000000000000000000000000000000000000000000000aa0": "0aa0",
+ "0x0000000000000000000000000000000000000000000000000000000000000aaa": "0aaa",
+ "0x0000000000000000000000000000000000000000000000000000000000000ab4": "0ab4",
+ "0x0000000000000000000000000000000000000000000000000000000000000abe": "0abe",
+ "0x0000000000000000000000000000000000000000000000000000000000000ac8": "0ac8",
+ "0x0000000000000000000000000000000000000000000000000000000000000ad2": "0ad2",
+ "0x0000000000000000000000000000000000000000000000000000000000000adc": "0adc",
+ "0x0000000000000000000000000000000000000000000000000000000000000ae6": "0ae6",
+ "0x0000000000000000000000000000000000000000000000000000000000000af0": "0af0",
+ "0x0000000000000000000000000000000000000000000000000000000000000afa": "0afa",
+ "0x0000000000000000000000000000000000000000000000000000000000000b04": "0b04",
+ "0x0000000000000000000000000000000000000000000000000000000000000b0e": "0b0e",
+ "0x0000000000000000000000000000000000000000000000000000000000000b18": "0b18",
+ "0x0000000000000000000000000000000000000000000000000000000000000b22": "0b22",
+ "0x0000000000000000000000000000000000000000000000000000000000000b2c": "0b2c",
+ "0x0000000000000000000000000000000000000000000000000000000000000b36": "0b36",
+ "0x0000000000000000000000000000000000000000000000000000000000000b40": "0b40",
+ "0x0000000000000000000000000000000000000000000000000000000000000b4a": "0b4a",
+ "0x0000000000000000000000000000000000000000000000000000000000000b54": "0b54",
+ "0x0000000000000000000000000000000000000000000000000000000000000b5e": "0b5e",
+ "0x0000000000000000000000000000000000000000000000000000000000000b68": "0b68",
+ "0x0000000000000000000000000000000000000000000000000000000000000b72": "0b72",
+ "0x0000000000000000000000000000000000000000000000000000000000000b7c": "0b7c",
+ "0x0000000000000000000000000000000000000000000000000000000000000b86": "0b86",
+ "0x0000000000000000000000000000000000000000000000000000000000000b90": "0b90",
+ "0x0000000000000000000000000000000000000000000000000000000000000b9a": "0b9a",
+ "0x0000000000000000000000000000000000000000000000000000000000000ba4": "0ba4",
+ "0x0000000000000000000000000000000000000000000000000000000000000bae": "0bae",
+ "0x0000000000000000000000000000000000000000000000000000000000000bb8": "0bb8",
+ "0x0000000000000000000000000000000000000000000000000000000000000bc2": "0bc2",
+ "0x0000000000000000000000000000000000000000000000000000000000000bcc": "0bcc",
+ "0x0000000000000000000000000000000000000000000000000000000000000bd6": "0bd6",
+ "0x0000000000000000000000000000000000000000000000000000000000000be0": "0be0",
+ "0x0000000000000000000000000000000000000000000000000000000000000bea": "0bea",
+ "0x0000000000000000000000000000000000000000000000000000000000000bf4": "0bf4",
+ "0x0000000000000000000000000000000000000000000000000000000000000bfe": "0bfe",
+ "0x0000000000000000000000000000000000000000000000000000000000000c08": "0c08",
+ "0x0000000000000000000000000000000000000000000000000000000000000c12": "0c12",
+ "0x0000000000000000000000000000000000000000000000000000000000000c1c": "0c1c",
+ "0x0000000000000000000000000000000000000000000000000000000000000c26": "0c26",
+ "0x0000000000000000000000000000000000000000000000000000000000000c30": "0c30",
+ "0x0000000000000000000000000000000000000000000000000000000000000c3a": "0c3a",
+ "0x0000000000000000000000000000000000000000000000000000000000000c44": "0c44",
+ "0x0000000000000000000000000000000000000000000000000000000000000c4e": "0c4e",
+ "0x0000000000000000000000000000000000000000000000000000000000000c58": "0c58",
+ "0x0000000000000000000000000000000000000000000000000000000000000c62": "0c62",
+ "0x0000000000000000000000000000000000000000000000000000000000000c6c": "0c6c",
+ "0x0000000000000000000000000000000000000000000000000000000000000c76": "0c76",
+ "0x0000000000000000000000000000000000000000000000000000000000000c80": "0c80",
+ "0x0000000000000000000000000000000000000000000000000000000000000c8a": "0c8a",
+ "0x0000000000000000000000000000000000000000000000000000000000000c94": "0c94",
+ "0x0000000000000000000000000000000000000000000000000000000000000c9e": "0c9e",
+ "0x0000000000000000000000000000000000000000000000000000000000000ca8": "0ca8",
+ "0x0000000000000000000000000000000000000000000000000000000000000cb2": "0cb2",
+ "0x0000000000000000000000000000000000000000000000000000000000000cbc": "0cbc",
+ "0x0000000000000000000000000000000000000000000000000000000000000cc6": "0cc6",
+ "0x0000000000000000000000000000000000000000000000000000000000000cd0": "0cd0",
+ "0x0000000000000000000000000000000000000000000000000000000000000cda": "0cda",
+ "0x0000000000000000000000000000000000000000000000000000000000000ce4": "0ce4",
+ "0x0000000000000000000000000000000000000000000000000000000000000cee": "0cee",
+ "0x0000000000000000000000000000000000000000000000000000000000000cf8": "0cf8",
+ "0x0000000000000000000000000000000000000000000000000000000000000d02": "0d02",
+ "0x0000000000000000000000000000000000000000000000000000000000000d0c": "0d0c",
+ "0x0000000000000000000000000000000000000000000000000000000000000d16": "0d16",
+ "0x0000000000000000000000000000000000000000000000000000000000000d20": "0d20",
+ "0x0000000000000000000000000000000000000000000000000000000000000d2a": "0d2a",
+ "0x0000000000000000000000000000000000000000000000000000000000000d34": "0d34",
+ "0x0000000000000000000000000000000000000000000000000000000000000d3e": "0d3e",
+ "0x0000000000000000000000000000000000000000000000000000000000000d48": "0d48",
+ "0x0000000000000000000000000000000000000000000000000000000000000d52": "0d52",
+ "0x0000000000000000000000000000000000000000000000000000000000000d5c": "0d5c",
+ "0x0000000000000000000000000000000000000000000000000000000000000d66": "0d66",
+ "0x0000000000000000000000000000000000000000000000000000000000000d70": "0d70",
+ "0x0000000000000000000000000000000000000000000000000000000000000d7a": "0d7a",
+ "0x0000000000000000000000000000000000000000000000000000000000000d84": "0d84",
+ "0x0000000000000000000000000000000000000000000000000000000000000d8e": "0d8e",
+ "0x0000000000000000000000000000000000000000000000000000000000000d98": "0d98",
+ "0x0000000000000000000000000000000000000000000000000000000000000da2": "0da2",
+ "0x0000000000000000000000000000000000000000000000000000000000000dac": "0dac",
+ "0x0000000000000000000000000000000000000000000000000000000000000db6": "0db6",
+ "0x0000000000000000000000000000000000000000000000000000000000000dc0": "0dc0",
+ "0x0000000000000000000000000000000000000000000000000000000000000dca": "0dca",
+ "0x0000000000000000000000000000000000000000000000000000000000000dd4": "0dd4",
+ "0x0000000000000000000000000000000000000000000000000000000000000dde": "0dde",
+ "0x0000000000000000000000000000000000000000000000000000000000000de8": "0de8",
+ "0x0000000000000000000000000000000000000000000000000000000000000df2": "0df2",
+ "0x0000000000000000000000000000000000000000000000000000000000000dfc": "0dfc",
+ "0x0000000000000000000000000000000000000000000000000000000000000e06": "0e06",
+ "0x0000000000000000000000000000000000000000000000000000000000000e10": "0e10",
+ "0x0000000000000000000000000000000000000000000000000000000000000e1a": "0e1a",
+ "0x0000000000000000000000000000000000000000000000000000000000000e24": "0e24",
+ "0x0000000000000000000000000000000000000000000000000000000000000e2e": "0e2e",
+ "0x0000000000000000000000000000000000000000000000000000000000000e38": "0e38",
+ "0x0000000000000000000000000000000000000000000000000000000000000e42": "0e42",
+ "0x0000000000000000000000000000000000000000000000000000000000000e4c": "0e4c",
+ "0x0000000000000000000000000000000000000000000000000000000000000e56": "0e56",
+ "0x0000000000000000000000000000000000000000000000000000000000000e60": "0e60",
+ "0x0000000000000000000000000000000000000000000000000000000000000e6a": "0e6a",
+ "0x0000000000000000000000000000000000000000000000000000000000000e74": "0e74",
+ "0x0000000000000000000000000000000000000000000000000000000000000e7e": "0e7e",
+ "0x0000000000000000000000000000000000000000000000000000000000000e88": "0e88",
+ "0x0000000000000000000000000000000000000000000000000000000000000e92": "0e92",
+ "0x0000000000000000000000000000000000000000000000000000000000000e9c": "0e9c",
+ "0x0000000000000000000000000000000000000000000000000000000000000ea6": "0ea6",
+ "0x0000000000000000000000000000000000000000000000000000000000000eb0": "0eb0",
+ "0x0000000000000000000000000000000000000000000000000000000000000eba": "0eba",
+ "0x0000000000000000000000000000000000000000000000000000000000000ec4": "0ec4",
+ "0x0000000000000000000000000000000000000000000000000000000000000ece": "0ece",
+ "0x0000000000000000000000000000000000000000000000000000000000000ed8": "0ed8",
+ "0x0000000000000000000000000000000000000000000000000000000000000ee2": "0ee2",
+ "0x0000000000000000000000000000000000000000000000000000000000000eec": "0eec",
+ "0x0000000000000000000000000000000000000000000000000000000000000ef6": "0ef6",
+ "0x0000000000000000000000000000000000000000000000000000000000000f00": "0f00",
+ "0x0000000000000000000000000000000000000000000000000000000000000f0a": "0f0a",
+ "0x0000000000000000000000000000000000000000000000000000000000000f14": "0f14",
+ "0x0000000000000000000000000000000000000000000000000000000000000f1e": "0f1e",
+ "0x0000000000000000000000000000000000000000000000000000000000000f28": "0f28",
+ "0x0000000000000000000000000000000000000000000000000000000000000f32": "0f32",
+ "0x0000000000000000000000000000000000000000000000000000000000000f3c": "0f3c",
+ "0x0000000000000000000000000000000000000000000000000000000000000f46": "0f46",
+ "0x0000000000000000000000000000000000000000000000000000000000000f50": "0f50",
+ "0x0000000000000000000000000000000000000000000000000000000000000f5a": "0f5a",
+ "0x0000000000000000000000000000000000000000000000000000000000000f64": "0f64",
+ "0x0000000000000000000000000000000000000000000000000000000000000f6e": "0f6e",
+ "0x0000000000000000000000000000000000000000000000000000000000000f78": "0f78",
+ "0x0000000000000000000000000000000000000000000000000000000000000f82": "0f82",
+ "0x0000000000000000000000000000000000000000000000000000000000000f8c": "0f8c",
+ "0x0000000000000000000000000000000000000000000000000000000000000f96": "0f96",
+ "0x0000000000000000000000000000000000000000000000000000000000000fa0": "0fa0",
+ "0x0000000000000000000000000000000000000000000000000000000000000faa": "0faa",
+ "0x0000000000000000000000000000000000000000000000000000000000000fb4": "0fb4",
+ "0x0000000000000000000000000000000000000000000000000000000000000fbe": "0fbe",
+ "0x0000000000000000000000000000000000000000000000000000000000000fc8": "0fc8",
+ "0x0000000000000000000000000000000000000000000000000000000000000fd2": "0fd2",
+ "0x0000000000000000000000000000000000000000000000000000000000000fdc": "0fdc",
+ "0x0000000000000000000000000000000000000000000000000000000000000fe6": "0fe6",
+ "0x0000000000000000000000000000000000000000000000000000000000000ff0": "0ff0",
+ "0x0000000000000000000000000000000000000000000000000000000000000ffa": "0ffa",
+ "0x0000000000000000000000000000000000000000000000000000000000001004": "1004",
+ "0x000000000000000000000000000000000000000000000000000000000000100e": "100e",
+ "0x0000000000000000000000000000000000000000000000000000000000001018": "1018",
+ "0x0000000000000000000000000000000000000000000000000000000000001022": "1022",
+ "0x000000000000000000000000000000000000000000000000000000000000102c": "102c",
+ "0x0000000000000000000000000000000000000000000000000000000000001036": "1036",
+ "0x0000000000000000000000000000000000000000000000000000000000001040": "1040",
+ "0x000000000000000000000000000000000000000000000000000000000000104a": "104a",
+ "0x0000000000000000000000000000000000000000000000000000000000001054": "1054",
+ "0x000000000000000000000000000000000000000000000000000000000000105e": "105e",
+ "0x0000000000000000000000000000000000000000000000000000000000001068": "1068",
+ "0x0000000000000000000000000000000000000000000000000000000000001072": "1072",
+ "0x000000000000000000000000000000000000000000000000000000000000107c": "107c",
+ "0x0000000000000000000000000000000000000000000000000000000000001086": "1086",
+ "0x0000000000000000000000000000000000000000000000000000000000001090": "1090",
+ "0x000000000000000000000000000000000000000000000000000000000000109a": "109a",
+ "0x00000000000000000000000000000000000000000000000000000000000010a4": "10a4",
+ "0x00000000000000000000000000000000000000000000000000000000000010ae": "10ae",
+ "0x00000000000000000000000000000000000000000000000000000000000010b8": "10b8",
+ "0x00000000000000000000000000000000000000000000000000000000000010c2": "10c2",
+ "0x00000000000000000000000000000000000000000000000000000000000010cc": "10cc",
+ "0x00000000000000000000000000000000000000000000000000000000000010d6": "10d6",
+ "0x00000000000000000000000000000000000000000000000000000000000010e0": "10e0",
+ "0x00000000000000000000000000000000000000000000000000000000000010ea": "10ea",
+ "0x00000000000000000000000000000000000000000000000000000000000010f4": "10f4",
+ "0x00000000000000000000000000000000000000000000000000000000000010fe": "10fe",
+ "0x0000000000000000000000000000000000000000000000000000000000001108": "1108",
+ "0x0000000000000000000000000000000000000000000000000000000000001112": "1112",
+ "0x000000000000000000000000000000000000000000000000000000000000111c": "111c",
+ "0x0000000000000000000000000000000000000000000000000000000000001126": "1126",
+ "0x0000000000000000000000000000000000000000000000000000000000001130": "1130",
+ "0x000000000000000000000000000000000000000000000000000000000000113a": "113a",
+ "0x0000000000000000000000000000000000000000000000000000000000001144": "1144",
+ "0x000000000000000000000000000000000000000000000000000000000000114e": "114e",
+ "0x0000000000000000000000000000000000000000000000000000000000001158": "1158",
+ "0x0000000000000000000000000000000000000000000000000000000000001162": "1162",
+ "0x000000000000000000000000000000000000000000000000000000000000116c": "116c",
+ "0x0000000000000000000000000000000000000000000000000000000000001176": "1176",
+ "0x0000000000000000000000000000000000000000000000000000000000001180": "1180",
+ "0x000000000000000000000000000000000000000000000000000000000000118a": "118a",
+ "0x0000000000000000000000000000000000000000000000000000000000001194": "1194",
+ "0x000000000000000000000000000000000000000000000000000000000000119e": "119e",
+ "0x00000000000000000000000000000000000000000000000000000000000011a8": "11a8",
+ "0x00000000000000000000000000000000000000000000000000000000000011b2": "11b2",
+ "0x00000000000000000000000000000000000000000000000000000000000011bc": "11bc",
+ "0x00000000000000000000000000000000000000000000000000000000000011c6": "11c6",
+ "0x00000000000000000000000000000000000000000000000000000000000011d0": "11d0",
+ "0x00000000000000000000000000000000000000000000000000000000000011da": "11da",
+ "0x00000000000000000000000000000000000000000000000000000000000011e4": "11e4",
+ "0x00000000000000000000000000000000000000000000000000000000000011ee": "11ee",
+ "0x00000000000000000000000000000000000000000000000000000000000011f8": "11f8",
+ "0x0000000000000000000000000000000000000000000000000000000000001202": "1202",
+ "0x000000000000000000000000000000000000000000000000000000000000120c": "120c",
+ "0x0000000000000000000000000000000000000000000000000000000000001216": "1216",
+ "0x0000000000000000000000000000000000000000000000000000000000001220": "1220",
+ "0x000000000000000000000000000000000000000000000000000000000000122a": "122a",
+ "0x0000000000000000000000000000000000000000000000000000000000001234": "1234",
+ "0x000000000000000000000000000000000000000000000000000000000000123e": "123e",
+ "0x0000000000000000000000000000000000000000000000000000000000001248": "1248",
+ "0x0000000000000000000000000000000000000000000000000000000000001252": "1252",
+ "0x000000000000000000000000000000000000000000000000000000000000125c": "125c",
+ "0x0000000000000000000000000000000000000000000000000000000000001266": "1266",
+ "0x0000000000000000000000000000000000000000000000000000000000001270": "1270",
+ "0x000000000000000000000000000000000000000000000000000000000000127a": "127a",
+ "0x0000000000000000000000000000000000000000000000000000000000001284": "1284",
+ "0x000000000000000000000000000000000000000000000000000000000000128e": "128e",
+ "0x0000000000000000000000000000000000000000000000000000000000001298": "1298",
+ "0x00000000000000000000000000000000000000000000000000000000000012a2": "12a2",
+ "0x00000000000000000000000000000000000000000000000000000000000012ac": "12ac",
+ "0x00000000000000000000000000000000000000000000000000000000000012b6": "12b6",
+ "0x00000000000000000000000000000000000000000000000000000000000012c0": "12c0",
+ "0x00000000000000000000000000000000000000000000000000000000000012ca": "12ca",
+ "0x00000000000000000000000000000000000000000000000000000000000012d4": "12d4",
+ "0x00000000000000000000000000000000000000000000000000000000000012de": "12de",
+ "0x00000000000000000000000000000000000000000000000000000000000012e8": "12e8",
+ "0x00000000000000000000000000000000000000000000000000000000000012f2": "12f2",
+ "0x00000000000000000000000000000000000000000000000000000000000012fc": "12fc",
+ "0x0000000000000000000000000000000000000000000000000000000000001306": "1306",
+ "0x0000000000000000000000000000000000000000000000000000000000001310": "1310",
+ "0x000000000000000000000000000000000000000000000000000000000000131a": "131a",
+ "0x0000000000000000000000000000000000000000000000000000000000001324": "1324",
+ "0x000000000000000000000000000000000000000000000000000000000000132e": "132e",
+ "0x0000000000000000000000000000000000000000000000000000000000001338": "1338",
+ "0x0000000000000000000000000000000000000000000000000000000000001342": "1342",
+ "0x000000000000000000000000000000000000000000000000000000000000134c": "134c",
+ "0x0000000000000000000000000000000000000000000000000000000000001356": "1356",
+ "0x0000000000000000000000000000000000000000000000000000000000001360": "1360",
+ "0x000000000000000000000000000000000000000000000000000000000000136a": "136a",
+ "0x0000000000000000000000000000000000000000000000000000000000001374": "1374",
+ "0x000000000000000000000000000000000000000000000000000000000000137e": "137e",
+ "0x0000000000000000000000000000000000000000000000000000000000001388": "1388",
+ "0x0000000000000000000000000000000000000000000000000000000000002347": "83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd",
+ "0x0000000000000000000000000000000000000000000000000000000000002351": "2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e",
+ "0x000000000000000000000000000000000000000000000000000000000000235b": "756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67",
+ "0x0000000000000000000000000000000000000000000000000000000000002365": "4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78",
+ "0x000000000000000000000000000000000000000000000000000000000000236f": "d0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5",
+ "0x0000000000000000000000000000000000000000000000000000000000002379": "60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089",
+ "0x0000000000000000000000000000000000000000000000000000000000002383": "6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca",
+ "0x000000000000000000000000000000000000000000000000000000000000238d": "36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8",
+ "0x0000000000000000000000000000000000000000000000000000000000002397": "c13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94",
+ "0x00000000000000000000000000000000000000000000000000000000000023a1": "8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b",
+ "0x00000000000000000000000000000000000000000000000000000000000023ab": "e958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629",
+ "0x00000000000000000000000000000000000000000000000000000000000023b5": "3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e",
+ "0x00000000000000000000000000000000000000000000000000000000000023bf": "346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad",
+ "0x00000000000000000000000000000000000000000000000000000000000023c9": "e62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546",
+ "0x00000000000000000000000000000000000000000000000000000000000023d3": "ffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d",
+ "0x00000000000000000000000000000000000000000000000000000000000023dd": "23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427",
+ "0x00000000000000000000000000000000000000000000000000000000000023e7": "47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd",
+ "0x00000000000000000000000000000000000000000000000000000000000023f1": "6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe",
+ "0x00000000000000000000000000000000000000000000000000000000000023fb": "efc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547",
+ "0x0000000000000000000000000000000000000000000000000000000000002405": "3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f",
+ "0x000000000000000000000000000000000000000000000000000000000000240f": "63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80",
+ "0x0000000000000000000000000000000000000000000000000000000000002419": "67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c",
+ "0x0000000000000000000000000000000000000000000000000000000000002423": "7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885",
+ "0x000000000000000000000000000000000000000000000000000000000000242d": "c8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f",
+ "0x0000000000000000000000000000000000000000000000000000000000002437": "e40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91",
+ "0x0000000000000000000000000000000000000000000000000000000000002441": "e82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470",
+ "0x000000000000000000000000000000000000000000000000000000000000244b": "84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d",
+ "0x0000000000000000000000000000000000000000000000000000000000002455": "e9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c",
+ "0x000000000000000000000000000000000000000000000000000000000000245f": "430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002469": "f7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf",
+ "0x0000000000000000000000000000000000000000000000000000000000002473": "e134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb",
+ "0x000000000000000000000000000000000000000000000000000000000000247d": "9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613",
+ "0x0000000000000000000000000000000000000000000000000000000000002487": "79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978",
+ "0x0000000000000000000000000000000000000000000000000000000000002491": "d908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611",
+ "0x000000000000000000000000000000000000000000000000000000000000249b": "e0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3",
+ "0x00000000000000000000000000000000000000000000000000000000000024a5": "2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae",
+ "0x00000000000000000000000000000000000000000000000000000000000024af": "523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc",
+ "0x00000000000000000000000000000000000000000000000000000000000024b9": "be3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7",
+ "0x00000000000000000000000000000000000000000000000000000000000024c3": "2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039",
+ "0x00000000000000000000000000000000000000000000000000000000000024cd": "7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc",
+ "0x00000000000000000000000000000000000000000000000000000000000024d7": "4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256",
+ "0x00000000000000000000000000000000000000000000000000000000000024e1": "c5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844",
+ "0x00000000000000000000000000000000000000000000000000000000000024eb": "0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b",
+ "0x00000000000000000000000000000000000000000000000000000000000024f5": "7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5",
+ "0x00000000000000000000000000000000000000000000000000000000000024ff": "2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059",
+ "0x0000000000000000000000000000000000000000000000000000000000002509": "d4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f",
+ "0x0000000000000000000000000000000000000000000000000000000000002513": "e651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf",
+ "0x000000000000000000000000000000000000000000000000000000000000251d": "5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6",
+ "0x0000000000000000000000000000000000000000000000000000000000002527": "57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa",
+ "0x0000000000000000000000000000000000000000000000000000000000002531": "217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13",
+ "0x000000000000000000000000000000000000000000000000000000000000253b": "14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b",
+ "0x0000000000000000000000000000000000000000000000000000000000002545": "e736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63",
+ "0x000000000000000000000000000000000000000000000000000000000000254f": "7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e",
+ "0x0000000000000000000000000000000000000000000000000000000000002559": "28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074",
+ "0x0000000000000000000000000000000000000000000000000000000000002563": "6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6",
+ "0x000000000000000000000000000000000000000000000000000000000000256d": "d5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb",
+ "0x0000000000000000000000000000000000000000000000000000000000002577": "20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b",
+ "0x0000000000000000000000000000000000000000000000000000000000002581": "91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131",
+ "0x000000000000000000000000000000000000000000000000000000000000258b": "743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774",
+ "0x0000000000000000000000000000000000000000000000000000000000002595": "cdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839",
+ "0x000000000000000000000000000000000000000000000000000000000000259f": "cc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1",
+ "0x00000000000000000000000000000000000000000000000000000000000025a9": "f67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb",
+ "0x00000000000000000000000000000000000000000000000000000000000025b3": "e20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579",
+ "0x00000000000000000000000000000000000000000000000000000000000025bd": "f982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb",
+ "0x00000000000000000000000000000000000000000000000000000000000025c7": "230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6",
+ "0x00000000000000000000000000000000000000000000000000000000000025d1": "b7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4",
+ "0x00000000000000000000000000000000000000000000000000000000000025db": "31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3",
+ "0x00000000000000000000000000000000000000000000000000000000000025e5": "ded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d",
+ "0x00000000000000000000000000000000000000000000000000000000000025ef": "a0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6",
+ "0x00000000000000000000000000000000000000000000000000000000000025f9": "1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f",
+ "0x0000000000000000000000000000000000000000000000000000000000002603": "34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6",
+ "0x000000000000000000000000000000000000000000000000000000000000260d": "774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b",
+ "0x0000000000000000000000000000000000000000000000000000000000002617": "d616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09",
+ "0x0000000000000000000000000000000000000000000000000000000000002621": "cdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19",
+ "0x000000000000000000000000000000000000000000000000000000000000262b": "ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b",
+ "0x0000000000000000000000000000000000000000000000000000000000002635": "cb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af",
+ "0x000000000000000000000000000000000000000000000000000000000000263f": "6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002649": "2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf",
+ "0x0000000000000000000000000000000000000000000000000000000000002653": "08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500",
+ "0x000000000000000000000000000000000000000000000000000000000000265d": "e437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69",
+ "0x0000000000000000000000000000000000000000000000000000000000002667": "89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080",
+ "0x0000000000000000000000000000000000000000000000000000000000002671": "b15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b",
+ "0x000000000000000000000000000000000000000000000000000000000000267b": "ad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002685": "9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f",
+ "0x000000000000000000000000000000000000000000000000000000000000268f": "bf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac",
+ "0x0000000000000000000000000000000000000000000000000000000000002699": "bb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f",
+ "0x00000000000000000000000000000000000000000000000000000000000026a3": "6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0",
+ "0x00000000000000000000000000000000000000000000000000000000000026ad": "4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed",
+ "0x00000000000000000000000000000000000000000000000000000000000026b7": "268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a",
+ "0x00000000000000000000000000000000000000000000000000000000000026c1": "7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562",
+ "0x00000000000000000000000000000000000000000000000000000000000026cb": "d59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3",
+ "0x00000000000000000000000000000000000000000000000000000000000026d5": "551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57",
+ "0x00000000000000000000000000000000000000000000000000000000000026df": "c1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978",
+ "0x00000000000000000000000000000000000000000000000000000000000026e9": "9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205",
+ "0x00000000000000000000000000000000000000000000000000000000000026f3": "a7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886",
+ "0x00000000000000000000000000000000000000000000000000000000000026fd": "6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165",
+ "0x0000000000000000000000000000000000000000000000000000000000002707": "8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b",
+ "0x0000000000000000000000000000000000000000000000000000000000002711": "562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801",
+ "0x000000000000000000000000000000000000000000000000000000000000271b": "d19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb",
+ "0x0000000000000000000000000000000000000000000000000000000000002725": "f087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860",
+ "0x000000000000000000000000000000000000000000000000000000000000272f": "f7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002739": "77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435",
+ "0x0000000000000000000000000000000000000000000000000000000000002743": "e3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c",
+ "0x000000000000000000000000000000000000000000000000000000000000274d": "c893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194",
+ "0x0000000000000000000000000000000000000000000000000000000000002757": "39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d",
+ "0x0000000000000000000000000000000000000000000000000000000000002761": "72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb",
+ "0x000000000000000000000000000000000000000000000000000000000000276b": "178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03",
+ "0x0000000000000000000000000000000000000000000000000000000000002775": "f7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946",
+ "0x000000000000000000000000000000000000000000000000000000000000277f": "16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54",
+ "0x0000000000000000000000000000000000000000000000000000000000002789": "0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90",
+ "0x0000000000000000000000000000000000000000000000000000000000002793": "7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2",
+ "0x000000000000000000000000000000000000000000000000000000000000279d": "6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6",
+ "0x00000000000000000000000000000000000000000000000000000000000027a7": "91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae",
+ "0x00000000000000000000000000000000000000000000000000000000000027b1": "a1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3",
+ "0x00000000000000000000000000000000000000000000000000000000000027bb": "8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf",
+ "0x00000000000000000000000000000000000000000000000000000000000027c5": "cc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f",
+ "0x00000000000000000000000000000000000000000000000000000000000027cf": "b0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de",
+ "0x00000000000000000000000000000000000000000000000000000000000027d9": "92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3",
+ "0x00000000000000000000000000000000000000000000000000000000000027e3": "f6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53",
+ "0x00000000000000000000000000000000000000000000000000000000000027ed": "ea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67",
+ "0x00000000000000000000000000000000000000000000000000000000000027f7": "543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002801": "095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2",
+ "0x000000000000000000000000000000000000000000000000000000000000280b": "144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f",
+ "0x0000000000000000000000000000000000000000000000000000000000002815": "7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c",
+ "0x000000000000000000000000000000000000000000000000000000000000281f": "9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4",
+ "0x0000000000000000000000000000000000000000000000000000000000002829": "fc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9",
+ "0x0000000000000000000000000000000000000000000000000000000000002833": "5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca",
+ "0x000000000000000000000000000000000000000000000000000000000000283d": "5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed",
+ "0x0000000000000000000000000000000000000000000000000000000000002847": "b40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2",
+ "0x0000000000000000000000000000000000000000000000000000000000002851": "70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7",
+ "0x000000000000000000000000000000000000000000000000000000000000285b": "43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5",
+ "0x0000000000000000000000000000000000000000000000000000000000002865": "b50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4",
+ "0x000000000000000000000000000000000000000000000000000000000000286f": "c14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd",
+ "0x0000000000000000000000000000000000000000000000000000000000002879": "86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2",
+ "0x0000000000000000000000000000000000000000000000000000000000002883": "0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5",
+ "0x000000000000000000000000000000000000000000000000000000000000288d": "a4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002897": "2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d",
+ "0x00000000000000000000000000000000000000000000000000000000000028a1": "fc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b",
+ "0x00000000000000000000000000000000000000000000000000000000000028ab": "949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35",
+ "0x00000000000000000000000000000000000000000000000000000000000028b5": "289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e",
+ "0x00000000000000000000000000000000000000000000000000000000000028bf": "bfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a",
+ "0x00000000000000000000000000000000000000000000000000000000000028c9": "7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150",
+ "0x00000000000000000000000000000000000000000000000000000000000028d3": "992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db",
+ "0x00000000000000000000000000000000000000000000000000000000000028dd": "da6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa",
+ "0x00000000000000000000000000000000000000000000000000000000000028e7": "65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f",
+ "0x00000000000000000000000000000000000000000000000000000000000028f1": "cc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6",
+ "0x00000000000000000000000000000000000000000000000000000000000028fb": "096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290",
+ "0x0000000000000000000000000000000000000000000000000000000000002905": "0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2",
+ "0x000000000000000000000000000000000000000000000000000000000000290f": "9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522",
+ "0x0000000000000000000000000000000000000000000000000000000000002919": "2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26",
+ "0x0000000000000000000000000000000000000000000000000000000000002923": "2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea",
+ "0x000000000000000000000000000000000000000000000000000000000000292d": "1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c",
+ "0x0000000000000000000000000000000000000000000000000000000000002937": "18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598",
+ "0x0000000000000000000000000000000000000000000000000000000000002941": "700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5",
+ "0x000000000000000000000000000000000000000000000000000000000000294b": "cad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312",
+ "0x0000000000000000000000000000000000000000000000000000000000002955": "a85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f",
+ "0x000000000000000000000000000000000000000000000000000000000000295f": "040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec",
+ "0x0000000000000000000000000000000000000000000000000000000000002969": "49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04",
+ "0x0000000000000000000000000000000000000000000000000000000000002973": "810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20",
+ "0x000000000000000000000000000000000000000000000000000000000000297d": "9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78",
+ "0x0000000000000000000000000000000000000000000000000000000000002987": "f68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742",
+ "0x0000000000000000000000000000000000000000000000000000000000002991": "9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4",
+ "0x000000000000000000000000000000000000000000000000000000000000299b": "d0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097",
+ "0x00000000000000000000000000000000000000000000000000000000000029a5": "43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe",
+ "0x00000000000000000000000000000000000000000000000000000000000029af": "54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd",
+ "0x00000000000000000000000000000000000000000000000000000000000029b9": "9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8",
+ "0x00000000000000000000000000000000000000000000000000000000000029c3": "4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34",
+ "0x00000000000000000000000000000000000000000000000000000000000029cd": "215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc",
+ "0x00000000000000000000000000000000000000000000000000000000000029d7": "d17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e",
+ "0x00000000000000000000000000000000000000000000000000000000000029e1": "875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637",
+ "0x00000000000000000000000000000000000000000000000000000000000029eb": "6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f",
+ "0x00000000000000000000000000000000000000000000000000000000000029f5": "f11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf",
+ "0x00000000000000000000000000000000000000000000000000000000000029ff": "bbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc",
+ "0x0000000000000000000000000000000000000000000000000000000000002a09": "71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e",
+ "0x0000000000000000000000000000000000000000000000000000000000002a13": "b90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea",
+ "0x0000000000000000000000000000000000000000000000000000000000002a1d": "4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4",
+ "0x0000000000000000000000000000000000000000000000000000000000002a27": "afb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282",
+ "0x0000000000000000000000000000000000000000000000000000000000002a31": "d73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95",
+ "0x0000000000000000000000000000000000000000000000000000000000002a3b": "c26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1",
+ "0x0000000000000000000000000000000000000000000000000000000000002a45": "fb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d",
+ "0x0000000000000000000000000000000000000000000000000000000000002a4f": "d08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98",
+ "0x0000000000000000000000000000000000000000000000000000000000002a59": "df979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd",
+ "0x0000000000000000000000000000000000000000000000000000000000002a63": "15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba",
+ "0x0000000000000000000000000000000000000000000000000000000000002a6d": "fd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c",
+ "0x0000000000000000000000000000000000000000000000000000000000002a77": "edad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572",
+ "0x0000000000000000000000000000000000000000000000000000000000002a81": "c2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c",
+ "0x0000000000000000000000000000000000000000000000000000000000002a8b": "5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446",
+ "0x0000000000000000000000000000000000000000000000000000000000002a95": "0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d",
+ "0x0000000000000000000000000000000000000000000000000000000000002a9f": "14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961",
+ "0x0000000000000000000000000000000000000000000000000000000000002aa9": "490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79",
+ "0x0000000000000000000000000000000000000000000000000000000000002ab3": "4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a",
+ "0x0000000000000000000000000000000000000000000000000000000000002abd": "133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002ac7": "a73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972",
+ "0x0000000000000000000000000000000000000000000000000000000000002ad1": "9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c",
+ "0x0000000000000000000000000000000000000000000000000000000000002adb": "ec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8",
+ "0x0000000000000000000000000000000000000000000000000000000000002ae5": "3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16",
+ "0x0000000000000000000000000000000000000000000000000000000000002aef": "ccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca",
+ "0x0000000000000000000000000000000000000000000000000000000000002af9": "74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af",
+ "0x0000000000000000000000000000000000000000000000000000000000002b03": "f6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7",
+ "0x0000000000000000000000000000000000000000000000000000000000002b0d": "7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9",
+ "0x0000000000000000000000000000000000000000000000000000000000002b17": "1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918",
+ "0x0000000000000000000000000000000000000000000000000000000000002b21": "c564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5",
+ "0x0000000000000000000000000000000000000000000000000000000000002b2b": "9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e",
+ "0x0000000000000000000000000000000000000000000000000000000000002b35": "6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045",
+ "0x0000000000000000000000000000000000000000000000000000000000002b3f": "417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a",
+ "0x0000000000000000000000000000000000000000000000000000000000002b49": "e910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23",
+ "0x0000000000000000000000000000000000000000000000000000000000002b53": "8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692",
+ "0x0000000000000000000000000000000000000000000000000000000000002b5d": "3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1",
+ "0x0000000000000000000000000000000000000000000000000000000000002b67": "07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637",
+ "0x0000000000000000000000000000000000000000000000000000000000002b71": "f4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef",
+ "0x0000000000000000000000000000000000000000000000000000000000002b7b": "5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4",
+ "0x0000000000000000000000000000000000000000000000000000000000002b85": "e98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b",
+ "0x0000000000000000000000000000000000000000000000000000000000002b8f": "d62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe",
+ "0x0000000000000000000000000000000000000000000000000000000000002b99": "4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098",
+ "0x0000000000000000000000000000000000000000000000000000000000002ba3": "36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a",
+ "0x0000000000000000000000000000000000000000000000000000000000002bad": "164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a",
+ "0x0000000000000000000000000000000000000000000000000000000000002bb7": "aa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010",
+ "0x0000000000000000000000000000000000000000000000000000000000002bc1": "99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5",
+ "0x0000000000000000000000000000000000000000000000000000000000002bcb": "30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb",
+ "0x0000000000000000000000000000000000000000000000000000000000002bd5": "a804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7",
+ "0x0000000000000000000000000000000000000000000000000000000000002bdf": "c554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64",
+ "0x0000000000000000000000000000000000000000000000000000000000002be9": "c89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203",
+ "0x0000000000000000000000000000000000000000000000000000000000002bf3": "44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6",
+ "0x0000000000000000000000000000000000000000000000000000000000002bfd": "ae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8",
+ "0x0000000000000000000000000000000000000000000000000000000000002c07": "3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1",
+ "0x0000000000000000000000000000000000000000000000000000000000002c11": "b52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b",
+ "0x0000000000000000000000000000000000000000000000000000000000002c1b": "ff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f",
+ "0x0000000000000000000000000000000000000000000000000000000000002c25": "70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52",
+ "0x0000000000000000000000000000000000000000000000000000000000002c2f": "e3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71",
+ "0x0000000000000000000000000000000000000000000000000000000000002c39": "2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176",
+ "0x0000000000000000000000000000000000000000000000000000000000002c43": "06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720",
+ "0x0000000000000000000000000000000000000000000000000000000000002c4d": "ebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb",
+ "0x0000000000000000000000000000000000000000000000000000000000002c57": "738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf",
+ "0x0000000000000000000000000000000000000000000000000000000000002c61": "ae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a",
+ "0x0000000000000000000000000000000000000000000000000000000000002c6b": "69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97",
+ "0x0000000000000000000000000000000000000000000000000000000000002c75": "4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4",
+ "0x0000000000000000000000000000000000000000000000000000000000002c7f": "d3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3",
+ "0x0000000000000000000000000000000000000000000000000000000000002c89": "d1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c",
+ "0x0000000000000000000000000000000000000000000000000000000000002c93": "1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e",
+ "0x0000000000000000000000000000000000000000000000000000000000002c9d": "ccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9",
+ "0x0000000000000000000000000000000000000000000000000000000000002ca7": "8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84",
+ "0x0000000000000000000000000000000000000000000000000000000000002cb1": "85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19",
+ "0x0000000000000000000000000000000000000000000000000000000000002cbb": "0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3",
+ "0x0000000000000000000000000000000000000000000000000000000000002cc5": "a7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57",
+ "0x0000000000000000000000000000000000000000000000000000000000002ccf": "da5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82",
+ "0x0000000000000000000000000000000000000000000000000000000000002cd9": "3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b",
+ "0x0000000000000000000000000000000000000000000000000000000000002ce3": "273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea",
+ "0x0000000000000000000000000000000000000000000000000000000000002ced": "7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9",
+ "0x0000000000000000000000000000000000000000000000000000000000002cf7": "f63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616",
+ "0x0000000000000000000000000000000000000000000000000000000000002d01": "a68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8",
+ "0x0000000000000000000000000000000000000000000000000000000000002d0b": "59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f",
+ "0x0000000000000000000000000000000000000000000000000000000000002d15": "4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43",
+ "0x0000000000000000000000000000000000000000000000000000000000002d1f": "52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6",
+ "0x0000000000000000000000000000000000000000000000000000000000002d29": "7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327",
+ "0x0000000000000000000000000000000000000000000000000000000000002d33": "ef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f",
+ "0x0000000000000000000000000000000000000000000000000000000000002d3d": "e978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2",
+ "0x0000000000000000000000000000000000000000000000000000000000002d47": "c3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819",
+ "0x0000000000000000000000000000000000000000000000000000000000002d51": "bd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351",
+ "0x0000000000000000000000000000000000000000000000000000000000002d5b": "99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002d65": "02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97",
+ "0x0000000000000000000000000000000000000000000000000000000000002d6f": "627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771",
+ "0x0000000000000000000000000000000000000000000000000000000000002d79": "c087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7",
+ "0x0000000000000000000000000000000000000000000000000000000000002d83": "f7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867",
+ "0x0000000000000000000000000000000000000000000000000000000000002d8d": "1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571",
+ "0x0000000000000000000000000000000000000000000000000000000000002d97": "72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2",
+ "0x0000000000000000000000000000000000000000000000000000000000002da1": "e69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91",
+ "0x0000000000000000000000000000000000000000000000000000000000002dab": "c3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577",
+ "0x0000000000000000000000000000000000000000000000000000000000002db5": "93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192",
+ "0x0000000000000000000000000000000000000000000000000000000000002dbf": "b07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558",
+ "0x0000000000000000000000000000000000000000000000000000000000002dc9": "ec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca",
+ "0x0000000000000000000000000000000000000000000000000000000000002dd3": "2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1",
+ "0x0000000000000000000000000000000000000000000000000000000000002ddd": "f4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95",
+ "0x0000000000000000000000000000000000000000000000000000000000002de7": "8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697",
+ "0x0000000000000000000000000000000000000000000000000000000000002df1": "a194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c",
+ "0x0000000000000000000000000000000000000000000000000000000000002dfb": "a255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507",
+ "0x0000000000000000000000000000000000000000000000000000000000002e05": "7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb",
+ "0x0000000000000000000000000000000000000000000000000000000000002e0f": "b04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9",
+ "0x0000000000000000000000000000000000000000000000000000000000002e19": "6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded",
+ "0x0000000000000000000000000000000000000000000000000000000000002e23": "fcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce",
+ "0x0000000000000000000000000000000000000000000000000000000000002e2d": "df880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3",
+ "0x0000000000000000000000000000000000000000000000000000000000002e37": "adfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f",
+ "0x0000000000000000000000000000000000000000000000000000000000002e41": "b264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31",
+ "0x0000000000000000000000000000000000000000000000000000000000002e4b": "f2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38",
+ "0x0000000000000000000000000000000000000000000000000000000000002e55": "41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362",
+ "0x0000000000000000000000000000000000000000000000000000000000002e5f": "4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002e69": "8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315",
+ "0x0000000000000000000000000000000000000000000000000000000000002e73": "fa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf",
+ "0x0000000000000000000000000000000000000000000000000000000000002e7d": "da5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3",
+ "0x0000000000000000000000000000000000000000000000000000000000002e87": "16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547",
+ "0x0000000000000000000000000000000000000000000000000000000000002e91": "b75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094",
+ "0x0000000000000000000000000000000000000000000000000000000000002e9b": "d087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d",
+ "0x0000000000000000000000000000000000000000000000000000000000002ea5": "bc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002eaf": "3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3",
+ "0x0000000000000000000000000000000000000000000000000000000000002eb9": "4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563",
+ "0x0000000000000000000000000000000000000000000000000000000000002ec3": "f6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0",
+ "0x0000000000000000000000000000000000000000000000000000000000002ecd": "1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1",
+ "0x0000000000000000000000000000000000000000000000000000000000002ed7": "c3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57",
+ "0x0000000000000000000000000000000000000000000000000000000000002ee1": "3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc",
+ "0x0000000000000000000000000000000000000000000000000000000000002eeb": "cb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb",
+ "0x0000000000000000000000000000000000000000000000000000000000002ef5": "3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c",
+ "0x0000000000000000000000000000000000000000000000000000000000002eff": "dd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3",
+ "0x0000000000000000000000000000000000000000000000000000000000002f09": "ace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002f13": "f6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01",
+ "0x0000000000000000000000000000000000000000000000000000000000002f1d": "a6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb",
+ "0x0000000000000000000000000000000000000000000000000000000000002f27": "9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8",
+ "0x0000000000000000000000000000000000000000000000000000000000002f31": "a44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9",
+ "0x0000000000000000000000000000000000000000000000000000000000002f3b": "ce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0",
+ "0x0000000000000000000000000000000000000000000000000000000000002f45": "4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894",
+ "0x0000000000000000000000000000000000000000000000000000000000002f4f": "414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80",
+ "0x0000000000000000000000000000000000000000000000000000000000002f59": "647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d",
+ "0x0000000000000000000000000000000000000000000000000000000000002f63": "fa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855",
+ "0x0000000000000000000000000000000000000000000000000000000000002f6d": "106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6",
+ "0x0000000000000000000000000000000000000000000000000000000000002f77": "494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a",
+ "0x0000000000000000000000000000000000000000000000000000000000002f81": "0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795",
+ "0x0000000000000000000000000000000000000000000000000000000000002f8b": "d860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd",
+ "0x0000000000000000000000000000000000000000000000000000000000002f95": "9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf",
+ "0x0000000000000000000000000000000000000000000000000000000000002f9f": "4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8",
+ "0x0000000000000000000000000000000000000000000000000000000000002fa9": "c56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686",
+ "0x0000000000000000000000000000000000000000000000000000000000002fb3": "7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002fbd": "89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015",
+ "0x0000000000000000000000000000000000000000000000000000000000002fc7": "5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff",
+ "0x0000000000000000000000000000000000000000000000000000000000002fd1": "9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8",
+ "0x0000000000000000000000000000000000000000000000000000000000002fdb": "31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159",
+ "0x0000000000000000000000000000000000000000000000000000000000002fe5": "828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d",
+ "0x0000000000000000000000000000000000000000000000000000000000002fef": "7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053",
+ "0x0000000000000000000000000000000000000000000000000000000000002ff9": "31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1",
+ "0x0000000000000000000000000000000000000000000000000000000000003003": "e33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0",
+ "0x000000000000000000000000000000000000000000000000000000000000300d": "78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c",
+ "0x0000000000000000000000000000000000000000000000000000000000003017": "2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee",
+ "0x0000000000000000000000000000000000000000000000000000000000003021": "e1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b",
+ "0x000000000000000000000000000000000000000000000000000000000000302b": "4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b",
+ "0x0000000000000000000000000000000000000000000000000000000000003035": "156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846",
+ "0x000000000000000000000000000000000000000000000000000000000000303f": "dfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607",
+ "0x0000000000000000000000000000000000000000000000000000000000003049": "395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074",
+ "0x0000000000000000000000000000000000000000000000000000000000003053": "84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f",
+ "0x000000000000000000000000000000000000000000000000000000000000305d": "f4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586",
+ "0x0000000000000000000000000000000000000000000000000000000000003067": "0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6",
+ "0x0000000000000000000000000000000000000000000000000000000000003071": "4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac",
+ "0x000000000000000000000000000000000000000000000000000000000000307b": "9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f",
+ "0x0000000000000000000000000000000000000000000000000000000000003085": "473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766",
+ "0x000000000000000000000000000000000000000000000000000000000000308f": "225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3",
+ "0x0000000000000000000000000000000000000000000000000000000000003099": "31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa",
+ "0x00000000000000000000000000000000000000000000000000000000000030a3": "4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a",
+ "0x00000000000000000000000000000000000000000000000000000000000030ad": "ae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802",
+ "0x00000000000000000000000000000000000000000000000000000000000030b7": "8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c",
+ "0x00000000000000000000000000000000000000000000000000000000000030c1": "c22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845",
+ "0x00000000000000000000000000000000000000000000000000000000000030cb": "7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce",
+ "0x00000000000000000000000000000000000000000000000000000000000030d5": "943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31",
+ "0x00000000000000000000000000000000000000000000000000000000000030df": "66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0",
+ "0x00000000000000000000000000000000000000000000000000000000000030e9": "ac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70",
+ "0x00000000000000000000000000000000000000000000000000000000000030f3": "2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce",
+ "0x00000000000000000000000000000000000000000000000000000000000030fd": "823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887",
+ "0x0000000000000000000000000000000000000000000000000000000000003107": "3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918",
+ "0x0000000000000000000000000000000000000000000000000000000000003111": "44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85",
+ "0x000000000000000000000000000000000000000000000000000000000000311b": "6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7",
+ "0x0000000000000000000000000000000000000000000000000000000000003125": "581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a",
+ "0x000000000000000000000000000000000000000000000000000000000000312f": "9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526",
+ "0x0000000000000000000000000000000000000000000000000000000000003139": "54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d",
+ "0x0000000000000000000000000000000000000000000000000000000000003143": "1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924",
+ "0x000000000000000000000000000000000000000000000000000000000000314d": "ad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92",
+ "0x0000000000000000000000000000000000000000000000000000000000003157": "e13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67",
+ "0x0000000000000000000000000000000000000000000000000000000000003161": "b45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d",
+ "0x000000000000000000000000000000000000000000000000000000000000316b": "9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707",
+ "0x0000000000000000000000000000000000000000000000000000000000003175": "5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0",
+ "0x000000000000000000000000000000000000000000000000000000000000317f": "d6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e",
+ "0x0000000000000000000000000000000000000000000000000000000000003189": "96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31",
+ "0x0000000000000000000000000000000000000000000000000000000000003193": "4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412",
+ "0x000000000000000000000000000000000000000000000000000000000000319d": "c95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea",
+ "0x00000000000000000000000000000000000000000000000000000000000031a7": "2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079",
+ "0x00000000000000000000000000000000000000000000000000000000000031b1": "18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490",
+ "0x00000000000000000000000000000000000000000000000000000000000031bb": "b47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478",
+ "0x00000000000000000000000000000000000000000000000000000000000031c5": "e4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e",
+ "0x00000000000000000000000000000000000000000000000000000000000031cf": "fc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659",
+ "0x00000000000000000000000000000000000000000000000000000000000031d9": "4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a",
+ "0x00000000000000000000000000000000000000000000000000000000000031e3": "84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b",
+ "0x00000000000000000000000000000000000000000000000000000000000031ed": "ff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612",
+ "0x00000000000000000000000000000000000000000000000000000000000031f7": "73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce",
+ "0x0000000000000000000000000000000000000000000000000000000000003201": "ed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215",
+ "0x000000000000000000000000000000000000000000000000000000000000320b": "5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4",
+ "0x0000000000000000000000000000000000000000000000000000000000003215": "867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926",
+ "0x000000000000000000000000000000000000000000000000000000000000321f": "0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217",
+ "0x0000000000000000000000000000000000000000000000000000000000003229": "8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075",
+ "0x0000000000000000000000000000000000000000000000000000000000003233": "4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4",
+ "0x000000000000000000000000000000000000000000000000000000000000323d": "ec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef",
+ "0x0000000000000000000000000000000000000000000000000000000000003247": "efdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554",
+ "0x0000000000000000000000000000000000000000000000000000000000003251": "551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b",
+ "0x000000000000000000000000000000000000000000000000000000000000325b": "137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a",
+ "0x0000000000000000000000000000000000000000000000000000000000003265": "fb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78",
+ "0x000000000000000000000000000000000000000000000000000000000000326f": "96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c",
+ "0x0000000000000000000000000000000000000000000000000000000000003279": "68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff",
+ "0x0000000000000000000000000000000000000000000000000000000000003283": "e2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd",
+ "0x000000000000000000000000000000000000000000000000000000000000328d": "48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288",
+ "0x0000000000000000000000000000000000000000000000000000000000003297": "5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae",
+ "0x00000000000000000000000000000000000000000000000000000000000032a1": "204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33",
+ "0x00000000000000000000000000000000000000000000000000000000000032ab": "b74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5",
+ "0x00000000000000000000000000000000000000000000000000000000000032b5": "af5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7",
+ "0x00000000000000000000000000000000000000000000000000000000000032bf": "c657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda",
+ "0x00000000000000000000000000000000000000000000000000000000000032c9": "a0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b",
+ "0x00000000000000000000000000000000000000000000000000000000000032d3": "c9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de",
+ "0x00000000000000000000000000000000000000000000000000000000000032dd": "c74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297",
+ "0x00000000000000000000000000000000000000000000000000000000000032e7": "1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b",
+ "0x00000000000000000000000000000000000000000000000000000000000032f1": "6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1",
+ "0x00000000000000000000000000000000000000000000000000000000000032fb": "60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a",
+ "0x0000000000000000000000000000000000000000000000000000000000003305": "c50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc",
+ "0x000000000000000000000000000000000000000000000000000000000000330f": "b860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f",
+ "0x0000000000000000000000000000000000000000000000000000000000003319": "21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb",
+ "0x0000000000000000000000000000000000000000000000000000000000003323": "80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7",
+ "0x000000000000000000000000000000000000000000000000000000000000332d": "a3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675",
+ "0x0000000000000000000000000000000000000000000000000000000000003337": "e69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0",
+ "0x0000000000000000000000000000000000000000000000000000000000003341": "221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4",
+ "0x000000000000000000000000000000000000000000000000000000000000334b": "dcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e",
+ "0x0000000000000000000000000000000000000000000000000000000000003355": "4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46",
+ "0x000000000000000000000000000000000000000000000000000000000000335f": "5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f",
+ "0x0000000000000000000000000000000000000000000000000000000000003369": "9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de",
+ "0x0000000000000000000000000000000000000000000000000000000000003373": "1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8",
+ "0x000000000000000000000000000000000000000000000000000000000000337d": "4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51",
+ "0x0000000000000000000000000000000000000000000000000000000000003387": "f653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c"
+ },
+ "key": "0x37d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42"
+ },
+ "0x00f691ca9e1403d01344ebbaca0201380cacc99c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c48e400de1f24b4de94c59068fcd91a028576d13a22f900a7fcbd8f4845bcf4"
+ },
+ "0x0300100f529a704d19736a8714837adbc934db7f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x97b25febb46f44607c87a3498088c605086df207c7ddcd8ee718836a516a9153"
+ },
+ "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4c310e1f5d2f2e03562c4a5c473ae044b9ee19411f07097ced41e85bd99c3364"
+ },
+ "0x046dc70a4eba21473beb6d9460d880b8cfd66613": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4fd7c8d583447b937576211163a542d945ac8c0a6e22d0c42ac54e2cbaff9281"
+ },
+ "0x04b85539570fb9501f65453dbfad410a467becdd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9e53f0a2ddb430d27f6fffa0a68b5f75db1d68e24113dcca6e33918cdae80846",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000019": "19",
+ "0x000000000000000000000000000000000000000000000000000000000000001a": "1a",
+ "0x000000000000000000000000000000000000000000000000000000000000001b": "1b"
+ },
+ "key": "0xd84f7711be2f8eca69c742153230995afb483855b7c555b08da330139cdb9579"
+ },
+ "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe99460a483f3369006e3edeb356b3653699f246ec71f30568617ebc702058f59"
+ },
+ "0x04d6c0c946716aac894fc1653383543a91faab60": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x98bb9ba48fda7bb8091271ab0e53d7e0022fb1f1fa8fa00814e193c7d4b91eb3"
+ },
+ "0x050c9c302e904c7786b69caa9dd5b27a6e571b72": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x818eaf5adb56c6728889ba66b6980cd66b41199f0007cdd905ae739405e3c630",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000077": "77",
+ "0x0000000000000000000000000000000000000000000000000000000000000078": "78",
+ "0x0000000000000000000000000000000000000000000000000000000000000079": "79"
+ },
+ "key": "0xc3ac56e9e7f2f2c2c089e966d1b83414951586c3afeb86300531dfa350e38929"
+ },
+ "0x06f647b157b8557a12979ba04cf5ba222b9747cf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaf38e0e6a4a4005507b5d3e9470e8ccc0273b74b6971f768cbdf85abeab8a95b"
+ },
+ "0x075198bfe61765d35f990debe90959d438a943ce": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1d38ada74301c31f3fd7d92dd5ce52dc37ae633e82ac29c4ef18dfc141298e26"
+ },
+ "0x075db7ab5778cd5491d3ed7ab64c1ec0818148f3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf84223f460140ad56af9836cfa6c1c58c1397abf599c214689bc881066020ff7"
+ },
+ "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcd07379b0120ad9a9c7fa47e77190be321ab107670f3115fec485bebb467307d"
+ },
+ "0x087d80f7f182dd44f184aa86ca34488853ebcc04": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x867bc89cf8d5b39f1712fbc77414bbd93012af454c226dcee0fb34ccc0017498"
+ },
+ "0x08d3b23dbfe8ef7965a8b5e4d9c21feddbc11491": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9a4a33f978d84e0aceb3ac3670c2e2df6c8ae27c189a96ed00b806d10ed7b4ee",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001c6": "01c6",
+ "0x00000000000000000000000000000000000000000000000000000000000001c7": "01c7",
+ "0x00000000000000000000000000000000000000000000000000000000000001c8": "01c8"
+ },
+ "key": "0x792cc9f20a61c16646d5b6136693e7789549adb7d8e35503d0004130ea6528b0"
+ },
+ "0x09b9c1875399cd724b1017f155a193713cb23732": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x47fa48e25d3669a9bb190c59938f4be49de2d083696eb939c3b4072ec67e43b1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000005e": "5e",
+ "0x000000000000000000000000000000000000000000000000000000000000005f": "5f",
+ "0x0000000000000000000000000000000000000000000000000000000000000060": "60"
+ },
+ "key": "0x23ddaac09188c12e5d88009afa4a34041175c5531f45be53f1560a1cbfec4e8a"
+ },
+ "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc7fc033fe9f00d24cb9c479ddc0598e592737c305263d088001d7419d16feffa"
+ },
+ "0x0badc617ca1bcb1cb1d5272f64b168cbf0e8f86f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xca39f5f4ee3c6b33efe7bc485439f97f9dc62f65852c7a1cdf54fab1e3b70429",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000002d": "2d",
+ "0x000000000000000000000000000000000000000000000000000000000000002e": "2e",
+ "0x000000000000000000000000000000000000000000000000000000000000002f": "2f"
+ },
+ "key": "0xc250f30c01f4b7910c2eb8cdcd697cf493f6417bb2ed61d637d625a85a400912"
+ },
+ "0x0c2c51a0990aee1d73c1228de158688341557508": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x28f25652ec67d8df6a2e33730e5d0983443e3f759792a0128c06756e8eb6c37f"
+ },
+ "0x0d336bc3778662a1252d29a6f7216055f7a582bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa5a91cf9e815fb55df14b3ee8c1325a988cb3b6dd34796c901385c3cc2992073",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000013f": "013f",
+ "0x0000000000000000000000000000000000000000000000000000000000000140": "0140",
+ "0x0000000000000000000000000000000000000000000000000000000000000141": "0141"
+ },
+ "key": "0x86a73e3c668eb065ecac3402c6dc912e8eb886788ea147c770f119dcd30780c6"
+ },
+ "0x0e4aea2bbb2ae557728f2661ee3639360f1d787a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x74ed78eb16016d7ff3a173ab1bbcee9daa8e358a9d6c9be5e84ba6f4a34cf96a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000d1": "d1",
+ "0x00000000000000000000000000000000000000000000000000000000000000d2": "d2",
+ "0x00000000000000000000000000000000000000000000000000000000000000d3": "d3"
+ },
+ "key": "0x517bd5fbe28e4368b0b9fcba13d5e81fb51babdf4ed63bd83885235ee67a8fa0"
+ },
+ "0x0ef32dec5f88a96c2eb042126e8ab982406e0267": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x181abdd5e212171007e085fdc284a84d42d5bfc160960d881ccb6a10005ff089"
+ },
+ "0x0ef96a52f4510f82b049ba991c401a8f5eb823e5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"
+ },
+ "0x0f228c3ba41142e702ee7306859026c99d3d2df5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xedd9b1f966f1dfe50234523b479a45e95a1a8ec4a057ba5bfa7b69a13768197c"
+ },
+ "0x0fdcca8fde6d69ecbc9bfadb056ecf62d1966370": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x493f90435402df0907019bffc6dd25a17ce4acd6eb6077ef94c1626f0d77c9f0",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000f9": "f9",
+ "0x00000000000000000000000000000000000000000000000000000000000000fa": "fa",
+ "0x00000000000000000000000000000000000000000000000000000000000000fb": "fb"
+ },
+ "key": "0xfb5a31c5cfd33dce2c80a30c5efc28e5f4025624adcc2205a2504a78c57bdd1c"
+ },
+ "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb7d9d175039df1ba52c734547844f8805252893c029f7dbba9a63f8bce3ee306"
+ },
+ "0x0fed138ec52bab88db6c068df9125936c7c3e11b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x66eb16071ba379bf0c632fcb52f9175a656bef62adf0bef5349a7f5a6aad5d88",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000176": "0176",
+ "0x0000000000000000000000000000000000000000000000000000000000000177": "0177",
+ "0x0000000000000000000000000000000000000000000000000000000000000178": "0178"
+ },
+ "key": "0x255ec86eac03ba59f6dfcaa02128adbb22c561ae0c49e9e62e4fff363750626e"
+ },
+ "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9d42947ac5e61285567f65d4b400d90343dbd3192534c4c1f9d941c04f48f17c"
+ },
+ "0x1037044fabf0421617c47c74681d7cc9c59f136c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2290ea88cc63f09ab5e8c989a67e2e06613311801e39c84aae3badd8bb38409c"
+ },
+ "0x1042d41ee3def49e70df4e6c2be307b8015111e5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xdf3c1bfab8f7e70a8edf94792f91e4b6b2c2aa61caf687e4f6cb689d180adb80",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000095": "95",
+ "0x0000000000000000000000000000000000000000000000000000000000000096": "96",
+ "0x0000000000000000000000000000000000000000000000000000000000000097": "97"
+ },
+ "key": "0xc0ce77c6a355e57b89cca643e70450612c0744c9f0f8bf7dee51d6633dc850b1"
+ },
+ "0x104eb07eb9517a895828ab01a3595d3b94c766d5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfab4c6889992a3f4e96b005dfd851021e9e1ec2631a7ccd2a001433e35077968"
+ },
+ "0x1219c38638722b91f3a909f930d3acc16e309804": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd63070208c85e91c4c8c942cf52c416f0f3004c392a15f579350168f178dba2e"
+ },
+ "0x132432ce1ce64304f1d145eba1772f6edd6cdd17": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x729953a43ed6c913df957172680a17e5735143ad767bda8f58ac84ec62fbec5e"
+ },
+ "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99e56541f21039c9b7c63655333841a3415de0d27b79d18ade9ec7ecde7a1139"
+ },
+ "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9feaf0bd45df0fbf327c964c243b2fbc2f0a3cb48fedfeea1ae87ac1e66bc02f"
+ },
+ "0x1534b43c6dfa3695446aaf2aa07d123132cceceb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2a248c1755e977920284c8054fceeb20530dc07cd8bbe876f3ce02000818cc3a"
+ },
+ "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5264e880ecf7b80afda6cc2a151bac470601ff8e376af91aaf913a36a30c4009"
+ },
+ "0x16032a66fc011dab75416d2449fe1a3d5f4319d8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe3c79e424fd3a7e5bf8e0426383abd518604272fda87ecd94e1633d36f55bbb6"
+ },
+ "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xda81833ff053aff243d305449775c3fb1bd7f62c4a3c95dc9fb91b85e032faee"
+ },
+ "0x17333b15b4a5afd16cac55a104b554fc63cc8731": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4ceaf2371fcfb54a4d8bc1c804d90b06b3c32c9f17112b57c29b30a25cf8ca12"
+ },
+ "0x17b917f9d79d922b33e41582984712e32b3ad366": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x944f095afbd1383e5d0f91ef02895d398f4f76fdb6d86adf4765f25bdc304f5f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000081": "81",
+ "0x0000000000000000000000000000000000000000000000000000000000000082": "82",
+ "0x0000000000000000000000000000000000000000000000000000000000000083": "83"
+ },
+ "key": "0x13cfc46f6bdb7a1c30448d41880d061c3b8d36c55a29f1c0c8d95a8e882b8c25"
+ },
+ "0x18291b5f568e45ef0f16709b20c810e08750791f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x315ccc15883d06b4e743f8252c999bf1ee994583ff6114d89c0f3ddee828302b"
+ },
+ "0x189f40034be7a199f1fa9891668ee3ab6049f82d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6225e8f52719d564e8217b5f5260b1d1aac2bcb959e54bc60c5f479116c321b8"
+ },
+ "0x18ac3e7343f016890c510e93f935261169d9e3f5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xeba984db32038d7f4d71859a9a2fc6e19dde2e23f34b7cedf0c4bf228c319f17"
+ },
+ "0x19041ad672875015bc4041c24b581eafc0869aab": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfc8d513d1615c763865b984ea9c381032c14a983f80e5b2bd90b20b518329ed7"
+ },
+ "0x19129f84d987b13468846f822882dba0c50ca07d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2b8d12301a8af18405b3c826b6edcc60e8e034810f00716ca48bebb84c4ce7ab"
+ },
+ "0x194e49be24c1a94159f127aa9257ded12a0027db": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe0a3d3b839fca0f54745d0c50a048e424c9259f063b7416410a4422eeb7f837e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000180": "0180",
+ "0x0000000000000000000000000000000000000000000000000000000000000181": "0181",
+ "0x0000000000000000000000000000000000000000000000000000000000000182": "0182"
+ },
+ "key": "0xd57eafe6d4c5b91fe7114e199318ab640e55d67a1e9e3c7833253808b7dca75f"
+ },
+ "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7bac5af423cb5e417fa6c103c7cb9777e80660ce3735ca830c238b0d41610186"
+ },
+ "0x196d4a4c50eb47562596429fdecb4e3ac6b2a5fd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4e258aa445a0e2a8704cbc57bbe32b859a502cd6f99190162236300fabd86c4a"
+ },
+ "0x1a0eae9b9214d9269a4cff4982c45a67f4ca63aa": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5622801b1011de8403e44308bbf89a5809b7ad6586268cd72164523587f9b0e4",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000007c": "7c",
+ "0x000000000000000000000000000000000000000000000000000000000000007d": "7d",
+ "0x000000000000000000000000000000000000000000000000000000000000007e": "7e"
+ },
+ "key": "0x6a2c8498657ae4f0f7b1a02492c554f7f8a077e454550727890188f7423ba014"
+ },
+ "0x1ae59138ad95812304b117ee7b0d502bcb885af5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf164775805f47d8970d3282188009d4d7a2da1574fe97e5d7bc9836a2eed1d5b"
+ },
+ "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8ee17a1ec4bae15d8650323b996c55d5fa11a14ceec17ff1d77d725183904914"
+ },
+ "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9fd2e3a6de5a9da5badd719bd6e048acefa6d29399d8a99e19fd9626805b60b"
+ },
+ "0x1c972398125398a3665f212930758ae9518a8c94": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5d97d758e8800d37b6d452a1b1812d0afedba11f3411a17a8d51ee13a38d73f0"
+ },
+ "0x1e345d32d0864f75b16bde837543aa44fac35935": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd91acf305934a60c960a93fb00f927ec79308b8a919d2449faede722c2324cb3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000153": "0153",
+ "0x0000000000000000000000000000000000000000000000000000000000000154": "0154",
+ "0x0000000000000000000000000000000000000000000000000000000000000155": "0155"
+ },
+ "key": "0x961508ac3c93b30ee9a5a34a862c9fe1659e570546ac6c2e35da20f6d2bb5393"
+ },
+ "0x1e8ce8258fb47f55bf2c1473acb89a10074b9d0e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfb2ab315988de92dcf6ba848e756676265b56e4b84778a2c955fb2b3c848c51c"
+ },
+ "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7963685967117ffb6fd019663dc9e782ebb1234a38501bffc2eb5380f8dc303b"
+ },
+ "0x1f5746736c7741ae3e8fa0c6e947cade81559a86": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4e5bab4ebd077c3bbd8239995455989ea2e95427ddeed47d0618d9773332bb05"
+ },
+ "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc3791fc487a84f3731eb5a8129a7e26f357089971657813b48a821f5582514b3"
+ },
+ "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd9fa858992bc92386a7cebcd748eedd602bf432cb4b31607566bc92b85179624"
+ },
+ "0x2144780b7d04d82239c6570f84ab66376b63dfc9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x59936c15c454933ebc4989afa77e350f7640301b07341aead5f1b2668eeb1dad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000db": "db",
+ "0x00000000000000000000000000000000000000000000000000000000000000dc": "dc",
+ "0x00000000000000000000000000000000000000000000000000000000000000dd": "dd"
+ },
+ "key": "0xd37b6f5e5f0fa6a1b3fd15c9b3cf0fb595ba245ab912ad8059e672fa55f061b8"
+ },
+ "0x22694f8f2d0c62f63a25bd0057a80b89084c3b47": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2369a492b6cddcc0218617a060b40df0e7dda26abe48ba4e4108c532d3f2b84f"
+ },
+ "0x22b3f17adeb5f2ec22135d275fcc6e29f4989401": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa3abdaefbb886078dc6c5c72e4bc8d12e117dbbd588236c3fa7e0c69420eb24a"
+ },
+ "0x23262ad5ae496588bd793910b55ccf178fbd73f9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3437803101a8040aca273fb734d7965a87f823ff1ef78c7edcaad358eb98dee3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000171": "0171",
+ "0x0000000000000000000000000000000000000000000000000000000000000172": "0172",
+ "0x0000000000000000000000000000000000000000000000000000000000000173": "0173"
+ },
+ "key": "0xd8489fd0ce5e1806b24d1a7ce0e4ba8f0856b87696456539fcbb625a9bed2ccc"
+ },
+ "0x23b17315554bd2928c1f86dd526f7ee065a9607d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12e394ad62e51261b4b95c431496e46a39055d7ada7dbf243f938b6d79054630"
+ },
+ "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd72e318c1cea7baf503950c9b1bd67cf7caf2f663061fcde48d379047a38d075"
+ },
+ "0x23e6931c964e77b02506b08ebf115bad0e1eca66": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x174f1a19ff1d9ef72d0988653f31074cb59e2cf37cd9d2992c7b0dd3d77d84f9"
+ },
+ "0x24255ef5d941493b9978f3aabb0ed07d084ade19": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7583557e4e3918c95965fb610dc1424976c0eee606151b6dfc13640e69e5cb15"
+ },
+ "0x245843abef9e72e7efac30138a994bf6301e7e1d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe6e594c507ec0ac14917f7a8032f83cd0c3c58b461d459b822190290852c0e1"
+ },
+ "0x25261a7e8395b6e798e9b411c962fccc0fb31e38": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1017b10a7cc3732d729fe1f71ced25e5b7bc73dc62ca61309a8c7e5ac0af2f72"
+ },
+ "0x2553ec67bc75f75d7de13db86b14290f0f76e342": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x8078f3259d8199b7ca39d51e35d5b58d71ff148606731060386d323c5d19182c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000185": "0185",
+ "0x0000000000000000000000000000000000000000000000000000000000000186": "0186",
+ "0x0000000000000000000000000000000000000000000000000000000000000187": "0187"
+ },
+ "key": "0x0f30822f90f33f1d1ba6d1521a00935630d2c81ab12fa03d4a0f4915033134f3"
+ },
+ "0x2604439a795970de2047e339293a450c0565f625": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8678559b30b321b0f0420a4a3e8cecfde90c6e56766b78c1723062c93c1f041f"
+ },
+ "0x26704bf05b1da795939788ef05c8804dcf4b9009": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd60ee4ad5abbe759622fca5c536109b11e85aa2b48c0be2aebf01df597e74dba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000015d": "015d",
+ "0x000000000000000000000000000000000000000000000000000000000000015e": "015e",
+ "0x000000000000000000000000000000000000000000000000000000000000015f": "015f"
+ },
+ "key": "0xd1691564c6a5ab1391f0495634e749b9782de33756b6a058f4a9536c1b37bca6"
+ },
+ "0x2727d12b98783b2c3641b5672bcfcdf007971d28": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x59739ba3b156eb78f8bbb14bbf3dacdebfde95140f586db66f72e3117b94bb67",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000112": "0112",
+ "0x0000000000000000000000000000000000000000000000000000000000000113": "0113",
+ "0x0000000000000000000000000000000000000000000000000000000000000114": "0114"
+ },
+ "key": "0x88bf4121c2d189670cb4d0a16e68bdf06246034fd0a59d0d46fb5cec0209831e"
+ },
+ "0x2795044ce0f83f718bc79c5f2add1e52521978df": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xee9186a01e5e1122b61223b0e6acc6a069c9dcdb7307b0a296421272275f821b"
+ },
+ "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0a93a7231976ad485379a3b66c2d8983ba0b2ca87abaf0ca44836b2a06a2b102"
+ },
+ "0x27abdeddfe8503496adeb623466caa47da5f63ab": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x482814ea8f103c39dcf6ba7e75df37145bde813964d82e81e5d7e3747b95303d"
+ },
+ "0x281c93990bac2c69cf372c9a3b66c406c86cca82": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x81c0c51e15c9679ef12d02729c09db84220ba007efe7ced37a57132f6f0e83c9"
+ },
+ "0x2847213288f0988543a76512fab09684131809d9": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1b86a365b0f1583a07fc014602efc3f7dedfa90c66e738e9850719d34ac194e"
+ },
+ "0x28969cdfa74a12c82f3bad960b0b000aca2ac329": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x96d7104053877823b058fd9248e0bba2a540328e52ffad9bb18805e89ff579dc"
+ },
+ "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5e88e876a3af177e6daafe173b67f186a53f1771a663747f26b278c5acb4c219"
+ },
+ "0x2aac4746638ae1457010747a5b0fd2380a388f4f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5a82aff126ffebff76002b1e4de03c40ba494b81cb3fbc528f23e4be35a9afe6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000004b": "4b",
+ "0x000000000000000000000000000000000000000000000000000000000000004c": "4c",
+ "0x000000000000000000000000000000000000000000000000000000000000004d": "4d"
+ },
+ "key": "0x96c43ef9dce3410b78df97be69e7ccef8ed40d6e5bfe6582ea4cd7d577aa4569"
+ },
+ "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x303f57a0355c50bf1a0e1cf0fa8f9bdbc8d443b70f2ad93ac1c6b9c1d1fe29a2"
+ },
+ "0x2c0cd3c60f41d56ed7664dbce39630395614bf4b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x92d0f0954f4ec68bd32163a2bd7bc69f933c7cdbfc6f3d2457e065f841666b1c"
+ },
+ "0x2c1287779024c3a2f0924b54816d79b7e378907d": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x09d6e6745d272389182a510994e2b54d14b731fac96b9c9ef434bc1924315371"
+ },
+ "0x2c582db705c5721bb3ba59f4ec8e44fb4ef6b920": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe02ec497b66cb57679eb01de1bed2ad385a3d18130441a9d337bd14897e85d39"
+ },
+ "0x2d389075be5be9f2246ad654ce152cf05990b209": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9233a729f0468c9c309c48b82934c99ba1fd18447947b3bc0621adb7a5fc643"
+ },
+ "0x2d711642b726b04401627ca9fbac32f5c8530fb1": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe2149c5c256a5eb2578c013d33e3af6a87a514965c7ddf4a8131e2d978f09f9"
+ },
+ "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf33a7b66489679fa665dbfb4e6dd4b673495f853850eedc81d5f28bd2f4bd3b5"
+ },
+ "0x2e5f413fd8d378ed081a76e1468dad8cbf6e9ed5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe69f40f00148bf0d4dfa28b3f3f5a0297790555eca01a00e49517c6645096a6c"
+ },
+ "0x2eb6db4e06119ab31a3acf4f406ccbaa85e39c66": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaeaf19d38b69be4fb41cc89e4888708daa6b9b1c3f519fa28fe9a0da70cd8697"
+ },
+ "0x2f01c1c8c735a9a1b89898d3f14bbf61c91bf0fd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd2f394b4549b085fb9b9a8b313a874ea660808a4323ab2598ee15ddd1eb7e897"
+ },
+ "0x2fb64110da9389ce8567938a78f21b79222332f9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x415ded122ff7b6fe5862f5c443ea0375e372862b9001c5fe527d276a3a420280"
+ },
+ "0x2fc7b26c1fd501c57e57db3e876dc6ae7af6979b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3d20fedd270b3771706fe00a580a155439be57e8d550762def10906e83ed58bb",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000009f": "9f",
+ "0x00000000000000000000000000000000000000000000000000000000000000a0": "a0",
+ "0x00000000000000000000000000000000000000000000000000000000000000a1": "a1"
+ },
+ "key": "0xb9cddc73dfdacd009e55f27bdfd1cd37eef022ded5ce686ab0ffe890e6bf311e"
+ },
+ "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1eb1e18ae510d0066d60db5c2752e8c33604d4da24c38d2bda07c0cb6ad19e4"
+ },
+ "0x30c72b4fb390ff1d387821e210f3ab04fbe86d13": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xdf97f94bc47471870606f626fb7a0b42eed2d45fcc84dc1200ce62f7831da990",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000d6": "d6",
+ "0x00000000000000000000000000000000000000000000000000000000000000d7": "d7",
+ "0x00000000000000000000000000000000000000000000000000000000000000d8": "d8"
+ },
+ "key": "0x005e94bf632e80cde11add7d3447cd4ca93a5f2205d9874261484ae180718bd6"
+ },
+ "0x311df588ca5f412f970891e4cc3ac23648968ca2": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x974a4800ec4c0e998f581c6ee8c3972530989e97a179c6b2d40b8710c036e7b1"
+ },
+ "0x312e8fca5ac7dfc591031831bff6fede6ecf12a8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x64bfba8a4688bdee41c4b998e101567b8b56fea53d30ab85393f2d5b70c5da90"
+ },
+ "0x32c417b98c3d9bdd37550c0070310526347b4648": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x80cd4a7b601d4ba0cb09e527a246c2b5dd25b6dbf862ac4e87c6b189bfce82d7"
+ },
+ "0x33afd8244c9c1a37f5bddb3254cd08779a196458": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x210ce6d692a21d75de3764b6c0356c63a51550ebec2c01f56c154c24b1cf8888"
+ },
+ "0x33fc6e8ad066231eb5527d1a39214c1eb390985d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x87e33f70e1dd3c6ff68e3b71757d697fbeb20daae7a3cc8a7b1b3aa894592c50"
+ },
+ "0x360671abc40afd33ae0091e87e589fc320bf9e3d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12c1bb3dddf0f06f62d70ed5b7f7db7d89b591b3f23a838062631c4809c37196"
+ },
+ "0x3632d1763078069ca77b90e27061147a3b17ddc3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0463e52cda557221b0b66bd7285b043071df4c2ab146260f4e010970f3a0cccf"
+ },
+ "0x368b766f1e4d7bf437d2a709577a5210a99002b6": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4845aac9f26fcd628b39b83d1ccb5c554450b9666b66f83aa93a1523f4db0ab6"
+ },
+ "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcac96145454c46255fccca35343d9505164dabe319c17d81fda93cf1171e4c6e"
+ },
+ "0x38d0bd409abe8d78f9f0e0a03671e44e81c41c27": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x23a888c0a464ce461651fc1be2cfa0cb6ba4d1b125abe5b447eeadf9c5adf1f1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000167": "0167",
+ "0x0000000000000000000000000000000000000000000000000000000000000168": "0168",
+ "0x0000000000000000000000000000000000000000000000000000000000000169": "0169"
+ },
+ "key": "0xb58e67c536550fdf7140c8333ca62128df469a7270b16d528bc778909e0ac9a5"
+ },
+ "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x878040f46b1b4a065e6b82abd35421eb69eededc0c9598b82e3587ae47c8a651"
+ },
+ "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb5bca5e9ccef948c2431372315acc3b96e098d0e962b0c99d634a0475b670dc3"
+ },
+ "0x3c204ccddfebae334988367b5cf372387dc49ebd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc7bf2b34294065afb9a2c15f906cba1f7a1a9f0da34ea9c46603b52cae9028ec",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000194": "0194",
+ "0x0000000000000000000000000000000000000000000000000000000000000195": "0195",
+ "0x0000000000000000000000000000000000000000000000000000000000000196": "0196"
+ },
+ "key": "0x5ec55391e89ac4c3cf9e61801cd13609e8757ab6ed08687237b789f666ea781b"
+ },
+ "0x3c2572436de9a5f3c450071e391c8a9410ba517d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xbfba1bc2ac42655f5a97450be62b9430822232f1ce4998eaf5239b0c243b2b84",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000090": "90",
+ "0x0000000000000000000000000000000000000000000000000000000000000091": "91",
+ "0x0000000000000000000000000000000000000000000000000000000000000092": "92"
+ },
+ "key": "0x606059a65065e5f41347f38754e6ddb99b2d709fbff259343d399a4f9832b48f"
+ },
+ "0x3c5c4713708c72b519144ba8e595a8865505000d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x52d6d2913ae44bca11b5a116021db97c91a13e385ed48ba06628e74201231dba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001c1": "01c1",
+ "0x00000000000000000000000000000000000000000000000000000000000001c2": "01c2",
+ "0x00000000000000000000000000000000000000000000000000000000000001c3": "01c3"
+ },
+ "key": "0x37ddfcbcb4b2498578f90e0fcfef9965dcde4d4dfabe2f2836d2257faa169947"
+ },
+ "0x3cf2e7052ebd484a8d6fbca579ddb3cf920de9d3": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa95c88d7dc0f2373287c3b2407ba8e7419063833c424b06d8bb3b29181bb632e"
+ },
+ "0x3ee253436fc50e5a136ee01489a318afe2bbd572": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc57604a461c94ecdac12dbb706a52b32913d72253baffb8906e742724ae12449",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001b2": "01b2",
+ "0x00000000000000000000000000000000000000000000000000000000000001b3": "01b3",
+ "0x00000000000000000000000000000000000000000000000000000000000001b4": "01b4"
+ },
+ "key": "0xaf7c37d08a73483eff9ef5054477fb5d836a184aa07c3edb4409b9eb22dd56ca"
+ },
+ "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb40cc623b26a22203675787ca05b3be2c2af34b6b565bab95d43e7057e458684"
+ },
+ "0x3f79bb7b435b05321651daefd374cdc681dc06fa": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8c7bfaa19ea367dec5272872114c46802724a27d9b67ea3eed85431df664664e"
+ },
+ "0x3fba9ae304c21d19f50c23db133073f4f9665fc1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0b564e4a0203cbcec8301709a7449e2e7371910778df64c89f48507390f2d129"
+ },
+ "0x402f57de890877def439a753fcc0c37ac7808ef5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5c20f6ee05edbb60beeab752d87412b2f6e12c8feefa2079e6bd989f814ed4da"
+ },
+ "0x40b7ab67fb92dbcb4ff4e39e1155cad2fa066523": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd352b05571154d9a2061143fe6df190a740a2d321c59eb94a54acb7f3054e489"
+ },
+ "0x414a21e525a759e3ffeb22556be6348a92d5a13e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x15293aec87177f6c88f58bc51274ba75f1331f5cb94f0c973b1deab8b3524dfe"
+ },
+ "0x417fe11f58b6a2d089826b60722fbed1d2db96dd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd5e252ab2fba10107258010f154445cf7dffc42b7d8c5476de9a7adb533d73f1"
+ },
+ "0x41b45640640c98c953feef23468e0d275515f82f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x82b326641825378faa11c641c916f2e22c01080f487de0463e30d5e32b960f97",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000013a": "013a",
+ "0x000000000000000000000000000000000000000000000000000000000000013b": "013b",
+ "0x000000000000000000000000000000000000000000000000000000000000013c": "013c"
+ },
+ "key": "0xc2406cbd93e511ef493ac81ebe2b6a3fbecd05a3ba52d82a23a88eeb9d8604f0"
+ },
+ "0x426fcdc383c8becb38926ec0569ec4a810105fab": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6bd9fb206b22c76b4f9630248940855b842c684db89adff0eb9371846ea625a9"
+ },
+ "0x4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa13bfef92e05edee891599aa5e447ff2baa1708d9a6473a04ef66ab94f2a11e4"
+ },
+ "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb66092bc3624d84ff94ee42b097e846baf6142197d2c31245734d56a275c8eb9"
+ },
+ "0x452705f08c621987b14d5f729ca81829041f6373": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xac7183ebb421005a660509b070d3d47fc4e134cb7379c31dc35dc03ebd02e1cf"
+ },
+ "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x465311df0bf146d43750ed7d11b0451b5f6d5bfc69b8a216ef2f1c79c93cd848"
+ },
+ "0x45f83d17e10b34fca01eb8f4454dac34a777d940": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6dc09fdec00aa9a30dd8db984406a33e3ca15e35222a74773071207a5e56d2c2"
+ },
+ "0x469542b3ece7ae501372a11c673d7627294a85ca": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6dbe5551f50400859d14228606bf221beff07238bfa3866454304abb572f9512"
+ },
+ "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8b76305d3f00d33f77bd41496b4144fd3d113a2ec032983bd5830a8b73f61cf0"
+ },
+ "0x46b61db0aac95a332cecadad86e52531e578cf1f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5677600b2af87d21fdab2ac8ed39bd1be2f790c04600de0400c1989040d9879c"
+ },
+ "0x478508483cbb05defd7dcdac355dadf06282a6f2": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5fc13d7452287b5a8e3c3be9e4f9057b5c2dd82aeaff4ed892c96fc944ec31e7"
+ },
+ "0x47ce7195b6d53aaa737ff17d57db20d0d4874ef1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3d0e2ba537f35941068709450f25fee45aaf4dc6ae2ed22ad12e0743ac7c54a7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000108": "0108",
+ "0x0000000000000000000000000000000000000000000000000000000000000109": "0109",
+ "0x000000000000000000000000000000000000000000000000000000000000010a": "010a"
+ },
+ "key": "0x0579e46a5ed8a88504ac7d579b12eb346fbe4fd7e281bdd226b891f8abed4789"
+ },
+ "0x47dc540c94ceb704a23875c11273e16bb0b8a87a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x025f478d53bf78add6fa3708d9e061d59bfe14b21329b2a4cf1156d4f81b3d2d"
+ },
+ "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x05f6de281d8c2b5d98e8e01cd529bd76416b248caf11e0552047c5f1d516aab6"
+ },
+ "0x4816ce9dd68c07ab1e12b5ddc4dbef38792751c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x93843d6fa1fe5709a3035573f61cc06832f0377544d16d3a0725e78a0fa0267c"
+ },
+ "0x48701721ec0115f04bc7404058f6c0f386946e09": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12be3bf1f9b1dab5f908ca964115bee3bcff5371f84ede45bc60591b21117c51"
+ },
+ "0x494d799e953876ac6022c3f7da5e0f3c04b549be": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x04d9aa4f67f8b24d70a0ffd757e82456d9184113106b7d9e8eb6c3e8a8df27ee"
+ },
+ "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5c1d92594d6377fe6423257781b382f94dffcde4fadbf571aa328f6eb18f8fcd"
+ },
+ "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf16522fc36907ee1e9948240b0c1d1d105a75cc63b71006f16c20d79ad469bd7"
+ },
+ "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2116ab29b4cb8547af547fe472b7ce30713f234ed49cb1801ea6d3cf9c796d57"
+ },
+ "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x246cc8a2b79a30ec71390d829d0cb37cce1b953e89cb14deae4945526714a71c"
+ },
+ "0x4ba91e785d2361ddb198bcd71d6038305021a9b8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99ce1680f73f2adfa8e6bed135baa3360e3d17f185521918f9341fc236526321"
+ },
+ "0x4bfa260a661d68110a7a0a45264d2d43af9727de": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6f358b4e903d31fdd5c05cddaa174296bb30b6b2f72f1ff6410e6c1069198989"
+ },
+ "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5602444769b5fd1ddfca48e3c38f2ecad326fe2433f22b90f6566a38496bd426"
+ },
+ "0x4f362f9093bb8e7012f466224ff1237c0746d8c8": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcb6f450b4720c6b36d3a12271e35ace27f1d527d46b073771541ad39cc59398d"
+ },
+ "0x4f3e7da249f34e3cc8b261a7dc5b2d8e1cd85b78": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4d79fea6c7fef10cb0b5a8b3d85b66836a131bec0b04d891864e6fdb9794af75"
+ },
+ "0x4fb733bedb74fec8d65bedf056b935189a289e92": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa02abeb418f26179beafd96457bda8c690c6b1f3fbabac392d0920863edddbc6"
+ },
+ "0x4fffb6fbd0372228cb5e4d1f033a29f30cb668c8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcd3e75299e967d5f88d306be905a134343b224d3fd5a861b1a690de0e2dfe1ba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000b3": "b3",
+ "0x00000000000000000000000000000000000000000000000000000000000000b4": "b4",
+ "0x00000000000000000000000000000000000000000000000000000000000000b5": "b5"
+ },
+ "key": "0xf19ee923ed66b7b9264c2644aa20e5268a251b4914ca81b1dffee96ecb074cb1"
+ },
+ "0x50996999ff63a9a1a07da880af8f8c745a7fe72c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0e57ffa6cc6cbd96c1400150417dd9b30d958c58f63c36230a90a02b076f78b5"
+ },
+ "0x5123198d8a827fe0c788c409e7d2068afde64339": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa15773c9bfabef49e9825460ed95bf67b22b67d7806c840e0eb546d73c424768"
+ },
+ "0x526e1ff4cddb5033849a114c54eb71a176f6440c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x834718111121e2058fdb90a51f448028071857e11fbd55d43256174df56af01a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000c7": "c7",
+ "0x00000000000000000000000000000000000000000000000000000000000000c8": "c8",
+ "0x00000000000000000000000000000000000000000000000000000000000000c9": "c9"
+ },
+ "key": "0xb3a33a7f35ca5d08552516f58e9f76219716f9930a3a11ce9ae5db3e7a81445d"
+ },
+ "0x5371ac01baa0b8aa9cbfcd36a49e0b5f7fb7109d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x385b84d27059a3c78e7ea63a691eeb9c5376f77af11336762f8c18882ff7471a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000028": "28",
+ "0x0000000000000000000000000000000000000000000000000000000000000029": "29",
+ "0x000000000000000000000000000000000000000000000000000000000000002a": "2a"
+ },
+ "key": "0x7a08bb8417e6b18da3ba926568f1022c15553b2b0f1a32f2fd9e5a605469e54f"
+ },
+ "0x54314225e5efd5b8283d6ec2f7a03d5a92106374": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcade985c7fb6d371d0c7f7cb40178e7873d623eadcc37545798ec33a04bb2173"
+ },
+ "0x549abf1ae8db6de0d131a7b2b094c813ec1c6731": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x73bffc68a947fa19b7becd45661d22c870fac8dbf2b25703e1bdab5367f29543",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000086": "86",
+ "0x0000000000000000000000000000000000000000000000000000000000000087": "87",
+ "0x0000000000000000000000000000000000000000000000000000000000000088": "88"
+ },
+ "key": "0x910fb8b22867289cb57531ad39070ef8dbdbbe7aee941886a0e9f572b63ae9ee"
+ },
+ "0x5502b2da1a3a08ad258aa08c0c6e0312cf047e64": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xf73591e791af4c7c5fa039c33dd9d169cab14b1d9b0ca78bcc4e740d553b1acf",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000f4": "f4",
+ "0x00000000000000000000000000000000000000000000000000000000000000f5": "f5",
+ "0x00000000000000000000000000000000000000000000000000000000000000f6": "f6"
+ },
+ "key": "0x1d6ee979097e29141ad6b97ae19bb592420652b7000003c55eb52d5225c3307d"
+ },
+ "0x553f68e60e9f8ea74c831449525dc1bc4f6fc58e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x14f9f4b9445c7547d5a4671a38b0b12bbc0e7198c3b2934b82b695c8630d4972",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000126": "0126",
+ "0x0000000000000000000000000000000000000000000000000000000000000127": "0127",
+ "0x0000000000000000000000000000000000000000000000000000000000000128": "0128"
+ },
+ "key": "0x6ad3ba011e031431dc057c808b85346d58001b85b32a4b5c90ccccea0f82e170"
+ },
+ "0x56270eccd88bcd5ad8d2b08f82d96cd8dace4eb3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xb0700fe13dbaf94be50bcbec13a7b53e6cba034b29a3daba98fa861f5897213f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000063": "63",
+ "0x0000000000000000000000000000000000000000000000000000000000000064": "64",
+ "0x0000000000000000000000000000000000000000000000000000000000000065": "65"
+ },
+ "key": "0xcd6b3739d4dbce17dafc156790f2a3936eb75ce95e9bba039dd76661f40ea309"
+ },
+ "0x56d3f289b889e65c4268a1b56b3da2d3860d0afb": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x207f6c3e450546b0d1f3bc6a6faf5bfa0bff80396c55d567b834cf0e7c760347",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0a",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0b",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0c"
+ },
+ "key": "0xdc9ea08bdea052acab7c990edbb85551f2af3e1f1a236356ab345ac5bcc84562"
+ },
+ "0x56dc3a6c5ca1e1b773e5fdfc8a92e9a42feaa6e9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdbd66b6a89e01c76ae5f8cb0dcd8a24e787f58f015c9b08972bfabefa2eae0d5"
+ },
+ "0x579ab019e6b461188300c7fb202448d34669e5ff": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x18f4256a59e1b2e01e96ac465e1d14a45d789ce49728f42082289fc25cf32b8d"
+ },
+ "0x5820871100e656b0d84b950f0a557e37419bf17d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"
+ },
+ "0x58d77a134c11f45f9573d5c105fa6c8ae9b4237a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd9f987fec216556304eba05bcdae47bb736eea5a4183eb3e2c3a5045734ae8c7"
+ },
+ "0x591317752b32e45c9d44d925a4bcb4898f6b51fb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x89bde89df7f2d83344a503944bb347b847f208df837228bb2cdfd6c3228ca3df",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000011c": "011c",
+ "0x000000000000000000000000000000000000000000000000000000000000011d": "011d",
+ "0x000000000000000000000000000000000000000000000000000000000000011e": "011e"
+ },
+ "key": "0x88a5635dabc83e4e021167be484b62cbed0ecdaa9ac282dab2cd9405e97ed602"
+ },
+ "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3e57e37bc3f588c244ffe4da1f48a360fa540b77c92f0c76919ec4ee22b63599"
+ },
+ "0x5b35d3e1ac7a2c61d247046d38773decf4f2839a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x55cab9586acb40e66f66147ff3a059cfcbbad785dddd5c0cc31cb43edf98a5d5"
+ },
+ "0x5c019738b38feae2a8944bd644f7acd5e6f40e5c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xea83389383152270104093ed5dfe34ba403c75308133aa1be8f51ad804b3e9ee",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000103": "0103",
+ "0x0000000000000000000000000000000000000000000000000000000000000104": "0104",
+ "0x0000000000000000000000000000000000000000000000000000000000000105": "0105"
+ },
+ "key": "0xbccd85b63dba6300f84c561c5f52ce08a240564421e382e6f550ce0c12f2f632"
+ },
+ "0x5c04401b6f6a5e318c7b6f3106a6217d20008427": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6c37093a34016ae687da7aabb18e42009b71edff70a94733c904aea51a4853c1"
+ },
+ "0x5c23d95614dce3317e7be72de3c81479c3172a8a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x4f446329b5ee3d13d4f6b5e5f210ddc2d90fedba384b950e36a1d19af95c5cb1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0f",
+ "0x0000000000000000000000000000000000000000000000000000000000000010": "10",
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "11"
+ },
+ "key": "0x34a715e08b77afd68cde30b62e222542f3db90758370400c94d0563959a1d1a0"
+ },
+ "0x5c62e091b8c0565f1bafad0dad5934276143ae2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1bf7626cec5330a127e439e68e6ee1a1537e73b2de1aa6d6f7e06bc0f1e9d763"
+ },
+ "0x5d6bc8f87dd221a9f8c4144a256391979ff6426b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcc74930e1ee0e71a8081f247ec47442a3e5d00897966754a5b3ee8beb2c1160c"
+ },
+ "0x5df7504bc193ee4c3deadede1459eccca172e87c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4f458f480644b18c0e8207f405b82da7f75c7b3b5a34fe6771a0ecf644677f33"
+ },
+ "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3848b7da914222540b71e398081d04e3849d2ee0d328168a3cc173a1cd4e783b"
+ },
+ "0x5f4755a4bd689dc90425fb2fdb64a4b191a7264d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xaf867e6cbae810caa924b8b6ac3d8c0891831491a6906dd0be7ad324dcd1533d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000016c": "016c",
+ "0x000000000000000000000000000000000000000000000000000000000000016d": "016d",
+ "0x000000000000000000000000000000000000000000000000000000000000016e": "016e"
+ },
+ "key": "0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595"
+ },
+ "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd52564daf6d32a6ae29470732726859261f5a7409b4858101bd233ed5cc2f662"
+ },
+ "0x5f553e0d115af809cfc1396b4823378b2c7cced5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcc48f8d1c0dd6ec8ab7bbd792d94f6a74c8876b41bc859cee2228e8dad8207a4",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ae": "ae",
+ "0x00000000000000000000000000000000000000000000000000000000000000af": "af",
+ "0x00000000000000000000000000000000000000000000000000000000000000b0": "b0"
+ },
+ "key": "0xe3c2e12be28e2e36dc852e76dd32e091954f99f2a6480853cd7b9e01ec6cd889"
+ },
+ "0x6096d8459f8e424f514468098e6a0f2a871c815d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa20e6a21244af8ffccd5442297ad9b7a76ac72d7d8ac9e16f12fcc50e90b734e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000018f": "018f",
+ "0x0000000000000000000000000000000000000000000000000000000000000190": "0190",
+ "0x0000000000000000000000000000000000000000000000000000000000000191": "0191"
+ },
+ "key": "0x67cc0bf5341efbb7c8e1bdbf83d812b72170e6edec0263eeebdea6f107bbef0d"
+ },
+ "0x60d0debc5c81432ee294b9a06dcf58964224bbc2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5446b818f4c669669cd3314726ff134cf18c58a9a536df13c700610705a8b7c8",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000041": "41",
+ "0x0000000000000000000000000000000000000000000000000000000000000042": "42",
+ "0x0000000000000000000000000000000000000000000000000000000000000043": "43"
+ },
+ "key": "0x395b92f75f8e06b5378a84ba03379f025d785d8b626b2b6a1c84b718244b9a91"
+ },
+ "0x61774970e93c00a3e206a26c64707d3e33f89972": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x869acb929f591c54cb85842a51f296635e7d895798c547a293afe43e7bf7f417",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000006d": "6d",
+ "0x000000000000000000000000000000000000000000000000000000000000006e": "6e",
+ "0x000000000000000000000000000000000000000000000000000000000000006f": "6f"
+ },
+ "key": "0x07b49045c401bcc408f983d91a199c908cdf0d646049b5b83629a70b0117e295"
+ },
+ "0x6269e930eee66e89863db1ff8e4744d65e1fb6bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x419809ad1512ed1ab3fb570f98ceb2f1d1b5dea39578583cd2b03e9378bbe418"
+ },
+ "0x62b67e1f685b7fef51102005dddd27774be3fee3": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf462aaa112b195c148974ff796a81c0e7f9a972d04e60c178ac109102d593a88"
+ },
+ "0x6325c46e45d96f775754b39a17d733c4920d0038": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c463797c90e9ba42b45ae061ffaa6bbd0dad48bb4998f761e81859f2a904a49"
+ },
+ "0x63eb2d6ec7c526fd386631f71824bad098f39813": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfdaf2549ea901a469b3e91cd1c4290fab376ef687547046751e10b7b461ff297"
+ },
+ "0x6510225e743d73828aa4f73a3133818490bd8820": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6d72f72fd2fc8af227f75ab3ab199f12dfb939bdcff5f0acdac06a90084def8"
+ },
+ "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc2c26fbc0b7893d872fa528d6c235caab9164feb5b54c48381ff3d82c8244e77"
+ },
+ "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x00aa781aff39a8284ef43790e3a511b2caa50803613c5096bc782e8de08fa4c5"
+ },
+ "0x65c74c15a686187bb6bbf9958f494fc6b8006803": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x570210539713235b442bbbad50c58bee81b70efd2dad78f99e41a6c462faeb43"
+ },
+ "0x662fb906c0fb671022f9914d6bba12250ea6adfb": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb58e22a9ece8f9b3fdbaa7d17fe5fc92345df11d6863db4159647d64a34ff10b"
+ },
+ "0x66378d2edcc2176820e951f080dd6e9e15a0e695": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa02c8b02efb52fad3056fc96029467937c38c96d922250f6d2c0f77b923c85aa"
+ },
+ "0x670dc376ecca46823e13bab90acab2004fb1706c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xae440143d21e24a931b6756f6b3d50d337eaf0db3e6c34e36ab46fe2d99ef83e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000199": "0199",
+ "0x000000000000000000000000000000000000000000000000000000000000019a": "019a",
+ "0x000000000000000000000000000000000000000000000000000000000000019b": "019b"
+ },
+ "key": "0xdcda5b5203c2257997a574bdf85b2bea6d04829e8d7e048a709badc0fb99288c"
+ },
+ "0x6741149452787eb4384ebbd8456643f246217034": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x37e51740ad994839549a56ef8606d71ace79adc5f55c988958d1c450eea5ac2d"
+ },
+ "0x684888c0ebb17f374298b65ee2807526c066094c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb062c716d86a832649bccd53e9b11c77fc8a2a00ef0cc0dd2f561688a69d54f7"
+ },
+ "0x6922e93e3827642ce4b883c756b31abf80036649": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3be526914a7d688e00adca06a0c47c580cb7aa934115ca26006a1ed5455dd2ce"
+ },
+ "0x6a632187a3abf9bebb66d43368fccd612f631cbc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9de451c4f48bdb56c6df198ff8e1f5e349a84a4dc11de924707718e6ac897aa6"
+ },
+ "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x099d5081762b8b265e8ba4cd8e43f08be4715d903a0b1d96b3d9c4e811cbfb33"
+ },
+ "0x6b2884fef44bd4288621a2cda9f88ca07b480861": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6c5edf6a0fbdcff100e5ceafb63cba9aea355ba397a93fdb42a1a67b91375f8"
+ },
+ "0x6c49c19c40a44bbf1cf9d2d8741ec1126e815fc6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe00c49a65849d05cbf27a4d7788a68bc7b6013ae33411d40bc89282fc064f33d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001ad": "01ad",
+ "0x00000000000000000000000000000000000000000000000000000000000001ae": "01ae",
+ "0x00000000000000000000000000000000000000000000000000000000000001af": "01af"
+ },
+ "key": "0x0304d8eaccf0b942c468074250cbcb625ec5c4688b6b5d17d2a9bdd8dd565d5a"
+ },
+ "0x6ca60a92cbf88c7f527978dc183a22e774755551": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x52d034ca6ebd21c7ba62a2ad3b6359aa4a1cdc88bdaa64bb2271d898777293ab"
+ },
+ "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaa0ac2f707a3dc131374839d4ee969eeb1cb55adea878f56e7b5b83d187d925c"
+ },
+ "0x6d09a879576c0d941bea7833fb2285051b10d511": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaa0ffaa57269b865dccce764bf412de1dff3e7bba22ce319ef09e5907317b3e7"
+ },
+ "0x6d8b8f27857e10b21c0ff227110d7533cea03d0e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd3d9839f87c29fb007fd9928d38bbf84ef089f0cd640c838f4a42631e828c667",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000117": "0117",
+ "0x0000000000000000000000000000000000000000000000000000000000000118": "0118",
+ "0x0000000000000000000000000000000000000000000000000000000000000119": "0119"
+ },
+ "key": "0xfdbb8ddca8cecfe275da1ea1c36e494536f581d64ddf0c4f2e6dae9c7d891427"
+ },
+ "0x6e09a59a69b41abca97268b05595c074ad157872": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7a3870cc1ed4fc29e9ab4dd3218dbb239dd32c9bf05bff03e325b7ba68486c47"
+ },
+ "0x6e3d512a9328fa42c7ca1e20064071f88958ed93": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc1a6a0bf60ee7b3228ecf6cb7c9e5491fbf62642a3650d73314e976d9eb9a966"
+ },
+ "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x97f72ff641eb40ee1f1163544931635acb7550a0d44bfb9f4cc3aeae829b6d7d"
+ },
+ "0x6f80f6a318ea88bf0115d693f564139a5fb488f6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe73b3367629c8cb991f244ac073c0863ad1d8d88c2e180dd582cefda2de4415e"
+ },
+ "0x7021bf21ecdbefcb33d09e4b812a47b273aa1d5c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb9400acf38453fd206bc18f67ba04f55b807b20e4efc2157909d91d3a9f7bed2"
+ },
+ "0x706be462488699e89b722822dcec9822ad7d05a7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x78948842ff476b87544c189ce744d4d924ffd0907107a0dbaa4b71d0514f2225"
+ },
+ "0x717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc3c8e2dc64e67baa83b844263fe31bfe24de17bb72bfed790ab345b97b007816"
+ },
+ "0x7212449475dcc75d408ad62a9acc121d94288f6d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe333845edc60ed469a894c43ed8c06ec807dafd079b3c948077da56e18436290"
+ },
+ "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2fe5767f605b7b821675b223a22e4e5055154f75e7f3041fdffaa02e4787fab8"
+ },
+ "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "balance": "999999999999999999999518871495454239",
+ "nonce": 402,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4363d332a0d4df8582a84932729892387c623fe1ec42e2cfcbe85c183ed98e0e"
+ },
+ "0x75b9236dfe7d0e12eb21b6d175276a7c5d4e851d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc54ffffcbaa5b566a7cf37386c4ce5a338d558612343caaa99788343d516aa5f"
+ },
+ "0x77adfc95029e73b173f60e556f915b0cd8850848": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0993fd5b750fe4414f93c7880b89744abb96f7af1171ed5f47026bdf01df1874"
+ },
+ "0x788adf954fc28a524008ea1f2d0e87ae8893afdc": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x903f24b3d3d45bc50c082b2e71c7339c7060f633f868db2065ef611885abe37e"
+ },
+ "0x7a19252e8c9b457eb07f52d0ddbe16820b5b7830": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xab7bdc41a80ae9c8fcb9426ba716d8d47e523f94ffb4b9823512d259c9eca8cd"
+ },
+ "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x71dee9adfef0940a36336903bd6830964865180b98c0506f9bf7ba8f2740fbf9"
+ },
+ "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfcc08928955d4e5e17e17e46d5adbb8011e0a8a74cabbdd3e138c367e89a4428"
+ },
+ "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x55d0609468d8d4147a942e88cfc5f667daff850788d821889fbb03298924767c"
+ },
+ "0x7d80ad47bf8699f49853640b12ee55b1f51691f1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x65cf42efacdee07ed87a1c2de0752a4e3b959f33f9f9f8c77424ba759e01fcf2"
+ },
+ "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c3e44534b1398abc786e4591364c329e976dbde3b3ed3a4d55589de84bcb9a6"
+ },
+ "0x7dcef881c305fb208500cc9509db689047ed0967": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x6d2b8a074c78a0e5a8095d7a010d4961c639c541cf56fbb7049480cc8f199765",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001bc": "01bc",
+ "0x00000000000000000000000000000000000000000000000000000000000001bd": "01bd",
+ "0x00000000000000000000000000000000000000000000000000000000000001be": "01be"
+ },
+ "key": "0x68fc814efedf52ac8032da358ddcb61eab4138cb56b536884b86e229c995689c"
+ },
+ "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe04fdefc4f2eefd22721d5944411b282d0fcb1f9ac218f54793a35bca8199c25"
+ },
+ "0x7f774bb46e7e342a2d9d0514b27cee622012f741": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x720f25b62fc39426f70eb219c9dd481c1621821c8c0fa5367a1df6e59e3edf59"
+ },
+ "0x7fd02a3bb5d5926d4981efbf63b66de2a7b1aa63": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x7bf542bdaff5bfe3d33c26a88777773b5e525461093c36acb0dab591a319e509",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000032": "32",
+ "0x0000000000000000000000000000000000000000000000000000000000000033": "33",
+ "0x0000000000000000000000000000000000000000000000000000000000000034": "34"
+ },
+ "key": "0xfc3d2e27841c0913d10aa11fc4af4793bf376efe3d90ce8360aa392d0ecefa24"
+ },
+ "0x8074971c7d405ba1e70af34f5af7d564ddc495df": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x60fc69100d8e632667c80b94d434008823ed75416b71cbd112b4d0b02f563027",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000a4": "a4",
+ "0x00000000000000000000000000000000000000000000000000000000000000a5": "a5",
+ "0x00000000000000000000000000000000000000000000000000000000000000a6": "a6"
+ },
+ "key": "0x0e0e4646090b881949ec9991e48dec768ccd1980896aefd0d51fd56fd5689790"
+ },
+ "0x8120ff763f8283e574fc767702056b57fcc89003": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa2e7084ba9cec179519c7e8950c66ad3cba8586a60cff9f4d60c188dd621522a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000037": "37",
+ "0x0000000000000000000000000000000000000000000000000000000000000038": "38",
+ "0x0000000000000000000000000000000000000000000000000000000000000039": "39"
+ },
+ "key": "0x48e291f8a256ab15da8401c8cae555d5417a992dff3848926fa5b71655740059"
+ },
+ "0x8176caac8654abc74a905b137a37ecf7be2a9e95": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc4bab059ee8f7b36c82ada44d22129671d8f47f254ca6a48fded94a8ff591c88"
+ },
+ "0x81bda6e29da8c3e4806b64dfa1cd32cd9c8fa70e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd5e5e7be8a61bb5bfa271dfc265aa9744dea85de957b6cffff0ecb403f9697db"
+ },
+ "0x828a91cb304a669deff703bb8506a19eba28e250": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x936ac6251848da69a191cc91174e4b7583a12a43d896e243841ea98b65f264ad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000017b": "017b",
+ "0x000000000000000000000000000000000000000000000000000000000000017c": "017c",
+ "0x000000000000000000000000000000000000000000000000000000000000017d": "017d"
+ },
+ "key": "0xea810ea64a420acfa917346a4a02580a50483890cba1d8d1d158d11f1c59ed02"
+ },
+ "0x82c291ed50c5f02d7e15e655c6353c9278e1bbec": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x12de4544640fc8a027e1a912d776b90675bebfd50710c2876b2a24ec9eced367",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000cc": "cc",
+ "0x00000000000000000000000000000000000000000000000000000000000000cd": "cd",
+ "0x00000000000000000000000000000000000000000000000000000000000000ce": "ce"
+ },
+ "key": "0xa9970b3744a0e46b248aaf080a001441d24175b5534ad80755661d271b976d67"
+ },
+ "0x83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb17ea61d092bd5d77edd9d5214e9483607689cdcc35a30f7ea49071b3be88c64"
+ },
+ "0x847f88846c35337cbf57e37ffc18316a99ac2f14": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x310a2ac83d7e3e4d333102b1f7153bb0416b38427eb2e335dc6632d779a8b4af",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000bd": "bd",
+ "0x00000000000000000000000000000000000000000000000000000000000000be": "be",
+ "0x00000000000000000000000000000000000000000000000000000000000000bf": "bf"
+ },
+ "key": "0xbea55c1dc9f4a9fb50cbedc70448a4e162792b9502bb28b936c7e0a2fd7fe41d"
+ },
+ "0x84873854dba02cf6a765a6277a311301b2656a7f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3197690074092fe51694bdb96aaab9ae94dac87f129785e498ab171a363d3b40"
+ },
+ "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5162f18d40405c59ef279ad71d87fbec2bbfedc57139d56986fbf47daf8bcbf2"
+ },
+ "0x85f97e04d754c81dac21f0ce857adc81170d08c6": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2baa718b760c0cbd0ec40a3c6df7f2948b40ba096e6e4b116b636f0cca023bde"
+ },
+ "0x8642821710100a9a3ab10cd4223278a713318096": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4fbc5fc8df4f0a578c3be3549f1cb3ef135cbcdf75f620c7a1d412462e9b3b94"
+ },
+ "0x8749e96779cd1b9fa62b2a19870d9efc28acae09": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa3d8baf7ae7c96b1020753d12154e28cc7206402037c28c49c332a08cf7c4b51"
+ },
+ "0x87610688d55c08238eacf52864b5a5920a00b764": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2da86eb3d4ffdd895170bc7ef02b69a116fe21ac2ce45a3ed8e0bb8af17cf92b",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000fe": "fe",
+ "0x00000000000000000000000000000000000000000000000000000000000000ff": "ff",
+ "0x0000000000000000000000000000000000000000000000000000000000000100": "0100"
+ },
+ "key": "0x80a2c1f38f8e2721079a0de39f187adedcb81b2ab5ae718ec1b8d64e4aa6930e"
+ },
+ "0x878dedd9474cfa24d91bccc8b771e180cf01ac40": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7e1ef9f8d2fa6d4f8e6717c3dcccff352ea9b8b46b57f6106cdbeed109441799"
+ },
+ "0x882e7e5d12617c267a72948e716f231fa79e6d51": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x491b2cfba976b2e78bd9be3bc15c9964927205fc34c9954a4d61bbe8170ba533",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "05",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "06",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "07"
+ },
+ "key": "0xd2501ae11a14bf0c2283a24b7e77c846c00a63e71908c6a5e1caff201bad0762"
+ },
+ "0x88654f0e7be1751967bba901ed70257a3cb79940": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x30ce5b7591126d5464dfb4fc576a970b1368475ce097e244132b06d8cc8ccffe"
+ },
+ "0x892f60b39450a0e770f00a836761c8e964fd7467": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x74614a0c4ba7d7c70b162dad186b6cc77984ab4070534ad9757e04a5b776dcc8"
+ },
+ "0x8a5edab282632443219e051e4ade2d1d5bbc671c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc251a3acb75a90ff0cdca31da1408a27ef7dcaa42f18e648f2be1a28b35eac32"
+ },
+ "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x17984cc4b4aac0492699d37662b53ec2acf8cbe540c968b817061e4ed27026d0"
+ },
+ "0x8a8950f7623663222542c9469c73be3c4c81bbdf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaef83ad0ab332330a20e88cd3b5a4bcf6ac6c175ee780ed4183d11340df17833"
+ },
+ "0x8ba7e4a56d8d4a4a2fd7d0c8b9e6f032dc76cefb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x72e962dfe7e2828809f5906996dedeba50950140555b193fceb94f12fd6f0a22"
+ },
+ "0x8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "balance": "1",
+ "nonce": 1,
+ "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "01",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "02",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "03"
+ },
+ "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"
+ },
+ "0x8cf42eb93b1426f22a30bd22539503bdf838830c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0267c643f67b47cac9efacf6fcf0e4f4e1b273a727ded155db60eb9907939eb6"
+ },
+ "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb8d9b988ed60dbf5dca3e9d169343ca667498605f34fb6c30b45b2ed0f996f1a"
+ },
+ "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc13c19f53ce8b6411d6cdaafd8480dfa462ffdf39e2eb68df90181a128d88992"
+ },
+ "0x8fa24283a8c1cc8a0f76ac69362139a173592567": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xefaff7acc3ad3417517b21a92187d2e63d7a77bc284290ed406d1bc07ab3d885"
+ },
+ "0x8fb778e47caf2df14eca7a389955ca74ac8f4924": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xae2e7f1c933c6ca84ce8be811ef411dee773fb69508056d72448048ea1db5c47",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001ee": "01ee",
+ "0x00000000000000000000000000000000000000000000000000000000000001ef": "01ef",
+ "0x00000000000000000000000000000000000000000000000000000000000001f0": "01f0"
+ },
+ "key": "0x4973f6aa8cf5b1190fc95379aa01cff99570ee6b670725880217237fb49e4b24"
+ },
+ "0x90fd8e600ae1a7c69fa6ef2c537b533ca77366e8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xee9821621aa5ec9ab7d5878b2a995228adcdcacb710df522d2f91b434d3bdc79",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000c2": "c2",
+ "0x00000000000000000000000000000000000000000000000000000000000000c3": "c3",
+ "0x00000000000000000000000000000000000000000000000000000000000000c4": "c4"
+ },
+ "key": "0xbfaac98225451c56b2f9aec858cffc1eb253909615f3d9617627c793b938694f"
+ },
+ "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcb54add475a18ea02ab1adf9e2e73da7f23ecd3e92c4fa8ca4e8f588258cb5d3"
+ },
+ "0x923f800cf288500f8e53f04e4698c9b885dcf030": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb91824b28183c95881ada12404d5ee8af8123689a98054d41aaf4dd5bec50e90"
+ },
+ "0x9344b07175800259691961298ca11c824e65032d": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0x8e0388ecf64cfa76b3a6af159f77451519a7f9bb862e4cce24175c791fdcb0df",
+ "code": "0x60004381526020014681526020014181526020014881526020014481526020013281526020013481526020016000f3",
+ "key": "0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6"
+ },
+ "0x93747f73c18356c6b202f527f552436a0e06116a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x73cd1b7cd355f3f77c570a01100a616757408bb7abb78fe9ee1262b99688fcc4"
+ },
+ "0x9380b994c5738f68312f0e517902da81f63cdcfa": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x51b829f0f2c3de9cfbd94e47828a89940c329a49cd59540ca3c6d751a8d214d6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000135": "0135",
+ "0x0000000000000000000000000000000000000000000000000000000000000136": "0136",
+ "0x0000000000000000000000000000000000000000000000000000000000000137": "0137"
+ },
+ "key": "0x50d83ef5194d06752cd5594b57e809b135f24eedd124a51137feaaf049bc2efd"
+ },
+ "0x94d068bff1af651dd9d9c2e75adfb7eec6f66be7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x0754035aa4073381a211342b507de8e775c97c961096e6e2275df0bfcbb3a01c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000059": "59",
+ "0x000000000000000000000000000000000000000000000000000000000000005a": "5a",
+ "0x000000000000000000000000000000000000000000000000000000000000005b": "5b"
+ },
+ "key": "0x0cd2a7c53c76f228ed3aa7a29644b1915fde9ec22e0433808bf5467d914e7c7a"
+ },
+ "0x956062137518b270d730d4753000896de17c100a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5aa3b4a2ebdd402721c3953b724f4fe90900250bb4ef89ce417ec440da318cd6"
+ },
+ "0x96a1cabb97e1434a6e23e684dd4572e044c243ea": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe7c6828e1fe8c586b263a81aafc9587d313c609c6db8665a42ae1267cd9ade59"
+ },
+ "0x984c16459ded76438d98ce9b608f175c28a910a0": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4b9f335ce0bdffdd77fdb9830961c5bc7090ae94703d0392d3f0ff10e6a4fbab"
+ },
+ "0x99a1c0703485b331fa0302d6077b583082e242ea": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2cf292c1e382bdd0e72e126701d7b02484e6e272f4c0d814f5a6fae233fc7935",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000121": "0121",
+ "0x0000000000000000000000000000000000000000000000000000000000000122": "0122",
+ "0x0000000000000000000000000000000000000000000000000000000000000123": "0123"
+ },
+ "key": "0x734ee4981754a3f1403c4e8887d35addfb31717d93de3e00ede78368c230861e"
+ },
+ "0x99d40a710cb552eaaee1599d4040055859b1610d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x946bfb429d90f1b39bb47ada75376a8d90a5778068027d4b8b8514ac13f53eca"
+ },
+ "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd16e029e8c67c3f330cddaa86f82d31f523028404dfccd16d288645d718eb9da"
+ },
+ "0x9ae62b6d840756c238b5ce936b910bb99d565047": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8989651e80c20af78b37fdb693d74ecafc9239426ff1315e1fb7b674dcdbdb75"
+ },
+ "0x9b3cf956056937dfb6f9e3dc02e3979a4e421c0a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb1b2c1c59637202bb0e0d21255e44e0df719fe990be05f213b1b813e3d8179d7"
+ },
+ "0x9bb981f592bc1f9c31db67f30bbf1ff44b649886": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1ee7e0292fba90d9733f619f976a2655c484adb30135ef0c5153b5a2f32169df"
+ },
+ "0x9bfb328671c108c9ba4d45734d9f4462d8c9a9cb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc15b43e5f4853ec8da53ebde03de87b94afce42a9c02f648ad8bdb224604c4ad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001da": "01da",
+ "0x00000000000000000000000000000000000000000000000000000000000001db": "01db",
+ "0x00000000000000000000000000000000000000000000000000000000000001dc": "01dc"
+ },
+ "key": "0xa683478d0c949580d5738b490fac8129275bb6e921dfe5eae37292be3ee281b9"
+ },
+ "0x9defb0a9e163278be0e05aa01b312ec78cfa3726": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb31919583a759b75e83c14d00d0a89bb36adc452f73cee2933a346ccebaa8e31"
+ },
+ "0x9e59004e909ff011e5882332e421b6772e68ed10": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3897cb9b6f68765022f3c74f84a9f2833132858f661f4bc91ccd7a98f4e5b1ee"
+ },
+ "0x9f50ec6c8a595869d71ce8c3b1c17c02599a5cc3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2705244734f69af78e16c74784e1dc921cb8b6a98fe76f577cc441c831e973bf"
+ },
+ "0xa0794cd73f564baeeda23fa4ce635a3f8ae39621": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xfb79021e7fa54b9bd2df64f6db57897d52ae85f7c195af518de48200a1325e2c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ef": "ef",
+ "0x00000000000000000000000000000000000000000000000000000000000000f0": "f0",
+ "0x00000000000000000000000000000000000000000000000000000000000000f1": "f1"
+ },
+ "key": "0x60535eeb3ffb721c1688b879368c61a54e13f8881bdef6bd4a17b8b92e050e06"
+ },
+ "0xa12b147dd542518f44f821a4d436066c64932b0d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xae88076d02b19c4d09cb13fca14303687417b632444f3e30fc4880c225867be3"
+ },
+ "0xa179dbdd51c56d0988551f92535797bcf47ca0e7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6d1da4cf1127d654ed731a93105f481b315ecfc2f62b1ccb5f6d2717d6a40f9b"
+ },
+ "0xa1fce4363854ff888cff4b8e7875d600c2682390": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xad99b5bc38016547d5859f96be59bf18f994314116454def33ebfe9a892c508a"
+ },
+ "0xa225fe6df11a4f364234dd6a785a17cd38309acb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc1686045288a5952ad57de0e971bd25007723c9f749f49f391e715c27bf526c8",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000072": "72",
+ "0x0000000000000000000000000000000000000000000000000000000000000073": "73",
+ "0x0000000000000000000000000000000000000000000000000000000000000074": "74"
+ },
+ "key": "0x4e0ab2902f57bf2a250c0f87f088acc325d55f2320f2e33abd8e50ba273c9244"
+ },
+ "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfb9474d0e5538fcd99e8d8d024db335b4e057f4bcd359e85d78f4a5226b33272"
+ },
+ "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6188c4510d25576535a642b15b1dbdb8922fe572b099f504390f923c19799777"
+ },
+ "0xa64f449891f282b87e566036f981023dba4ed477": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x61176dbc05a8537d8de85f82a03b8e1049cea7ad0a9f0e5b60ee15fca6fe0d42",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000012b": "012b",
+ "0x000000000000000000000000000000000000000000000000000000000000012c": "012c",
+ "0x000000000000000000000000000000000000000000000000000000000000012d": "012d"
+ },
+ "key": "0x7c1edabb98857d64572f03c64ac803e4a14b1698fccffffd51675d99ee3ba217"
+ },
+ "0xa6515a495ec7723416665ebb54fc002bf1e9a873": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbbdc59572cc62c338fb6e027ab00c57cdeed233c8732680a56a5747141d20c7c"
+ },
+ "0xa6a54695341f038ad15e9e32f1096f5201236512": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe2a72f5bfbeba70fc9ab506237ba27c096a4e96c3968cabf5b1b2fb54431b5cf",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000023": "23",
+ "0x0000000000000000000000000000000000000000000000000000000000000024": "24",
+ "0x0000000000000000000000000000000000000000000000000000000000000025": "25"
+ },
+ "key": "0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9"
+ },
+ "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x02547b56492bfe767f3d18be2aab96441c449cd945770ef7ef8555acc505b2e4"
+ },
+ "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x913e2a02a28d71d595d7216a12311f6921a4caf40aeabf0f28edf937f1df72b4"
+ },
+ "0xa92bb60b61e305ddd888015189d6591b0eab0233": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdd1589b1fe1d9b4ca947f98ff324de7887af299d5490ed92ae40e95eec944118"
+ },
+ "0xa956ca63bf28e7da621475d6b077da1ab9812b3a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa090b66fbca46cb71abd1daa8d419d2c6e291094f52872978dfcb1c31ad7a900",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001e4": "01e4",
+ "0x00000000000000000000000000000000000000000000000000000000000001e5": "01e5",
+ "0x00000000000000000000000000000000000000000000000000000000000001e6": "01e6"
+ },
+ "key": "0xaad7b91d085a94c11a2f7e77dc95cfcfc5daf4f509ca4e0c0e493b86c6cbff78"
+ },
+ "0xaa0d6dfdb7588017c80ea088768a5f3d0cdeacdb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x89ecb0ceeea20ccd7d1b18cf1d35b7a2fd7b76ddc8d627f43304ed8b31b01248",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000144": "0144",
+ "0x0000000000000000000000000000000000000000000000000000000000000145": "0145",
+ "0x0000000000000000000000000000000000000000000000000000000000000146": "0146"
+ },
+ "key": "0xb990eaca858ea15fda296f3f47baa2939e8aa8bbccc12ca0c3746d9b5d5fb2ae"
+ },
+ "0xaa53ff4bb2334faf9f4447197ef69c39c0bb1379": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe547c0050253075b1be4210608bc639cffe70110194c316481235e738be961e7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ea": "ea",
+ "0x00000000000000000000000000000000000000000000000000000000000000eb": "eb",
+ "0x00000000000000000000000000000000000000000000000000000000000000ec": "ec"
+ },
+ "key": "0xed263a22f0e8be37bcc1873e589c54fe37fdde92902dc75d656997a7158a9d8c"
+ },
+ "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5a4a3feecfc77b402e938e28df0c4cbb874771cb3c5a92524f303cffb82a2862"
+ },
+ "0xab12a5f97f03edbff03eded9d1a2a1179d2fc69e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xba1d0afdfee510e8852f24dff964afd824bf36d458cf5f5d45f02f04b7c0b35d"
+ },
+ "0xab557835ab3e5c43bf34ac9b2ab730c5e0bc9967": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc9ea69dc9e84712b1349c9b271956cc0cb9473106be92d7a937b29e78e7e970e"
+ },
+ "0xab9025d4a9f93c65cd4fe978d38526860af0aa62": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x4ce79cd9645650f0a00effa86f6fea733cecea9ea26964828ff25cf0577bc974",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000009a": "9a",
+ "0x000000000000000000000000000000000000000000000000000000000000009b": "9b",
+ "0x000000000000000000000000000000000000000000000000000000000000009c": "9c"
+ },
+ "key": "0x17350c7adae7f08d7bbb8befcc97234462831638443cd6dfea186cbf5a08b7c7"
+ },
+ "0xabd693b23d55dec7d0d0cba2ecbc9298dc4edf02": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xafd54e81f3e415407f0812a678856f1b4068ed64a08b3f3bf5b2190fcfb2322d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001b7": "01b7",
+ "0x00000000000000000000000000000000000000000000000000000000000001b8": "01b8",
+ "0x00000000000000000000000000000000000000000000000000000000000001b9": "01b9"
+ },
+ "key": "0xbe7d987a9265c0e44e9c5736fb2eb38c41973ce96e5e8e6c3c713f9d50a079ff"
+ },
+ "0xabe2b033c497e091c1e494c98c178e8aa06bcb00": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2374954008440ca3d17b1472d34cc52a6493a94fb490d5fb427184d7d5fd1cbf"
+ },
+ "0xac4d51af4cb7bab4743fa57bc80b144d7a091268": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xfb00729a5f4f9a2436b999aa7159497a9cd88d155770f873a818b55052c5f067",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000149": "0149",
+ "0x000000000000000000000000000000000000000000000000000000000000014a": "014a",
+ "0x000000000000000000000000000000000000000000000000000000000000014b": "014b"
+ },
+ "key": "0xe42a85d04a1d0d9fe0703020ef98fa89ecdeb241a48de2db73f2feeaa2e49b0f"
+ },
+ "0xac7d8d5f6be7d251ec843ddbc09095150df59965": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa9580109be2f7d35b5360050c2ced74e5d4dea2f82d46e8d266ed89157636004",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000046": "46",
+ "0x0000000000000000000000000000000000000000000000000000000000000047": "47",
+ "0x0000000000000000000000000000000000000000000000000000000000000048": "48"
+ },
+ "key": "0x943f42ad91e8019f75695946d491bb95729f0dfc5dbbb953a7239ac73f208943"
+ },
+ "0xac9e61d54eb6967e212c06aab15408292f8558c4": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf2b9bc1163840284f3eb15c539972edad583cda91946f344f4cb57be15af9c8f"
+ },
+ "0xaceac762ff518b4cf93a6eebbc55987e7b79b2ce": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1960414a11f8896c7fc4243aba7ed8179b0bc6979b7c25da7557b17f5dee7bf7"
+ },
+ "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x58e416a0dd96454bd2b1fe3138c3642f5dee52e011305c5c3416d97bc8ba5cf0"
+ },
+ "0xad108e31c9632ad9e20614b3ca40644d32948dbb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2625f8a23d24a5dff6a79f632b1020593362a6ac622fa5237460bc67b0aa0ed3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001a3": "01a3",
+ "0x00000000000000000000000000000000000000000000000000000000000001a4": "01a4",
+ "0x00000000000000000000000000000000000000000000000000000000000001a5": "01a5"
+ },
+ "key": "0xdce547cc70c79575ef72c061502d6066db1cbce200bd904d5d2b20d4f1cb5963"
+ },
+ "0xae3f4619b0413d70d3004b9131c3752153074e45": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb1b2fd7758f73e25a2f9e72edde82995b2b32ab798bcffd2c7143f2fc8196fd8"
+ },
+ "0xae58b7e08e266680e93e46639a2a7e89fde78a6f": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe09e5f27b8a7bf61805df6e5fefc24eb6894281550c2d06250adecfe1e6581d7"
+ },
+ "0xaf17b30f5ab8e6a4d7a563bdb0194f3e0bd50209": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2434bfc643ec364116cd71519a397662b20c52d1adcff0b830e80a738e19f30e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000b8": "b8",
+ "0x00000000000000000000000000000000000000000000000000000000000000b9": "b9",
+ "0x00000000000000000000000000000000000000000000000000000000000000ba": "ba"
+ },
+ "key": "0x26ce7d83dfb0ab0e7f15c42aeb9e8c0c5dba538b07c8e64b35fb64a37267dd96"
+ },
+ "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1a28912018f78f7e754df6b9fcec33bea25e5a232224db622e0c3343cf079eff"
+ },
+ "0xaf2c6f1512d1cabedeaf129e0643863c57419732": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xad6a4a6ebd5166c9b5cc8cfbaec176cced40fa88c73d83c67f0c3ed426121ebc"
+ },
+ "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x053df2c3b574026812b154a99b13b626220af85cd01bb1693b1d42591054bce6"
+ },
+ "0xb0ee91ba61e8a3914a7eab120786e9e61bfe4faf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa14913d548ac1d3f9962a21a569fe52f1436b6d2f5ea4e36de13ea855ede54e0",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000068": "68",
+ "0x0000000000000000000000000000000000000000000000000000000000000069": "69",
+ "0x000000000000000000000000000000000000000000000000000000000000006a": "6a"
+ },
+ "key": "0x4bd8ef9873a5e85d4805dbcb0dbf6810e558ea175167549ef80545a9cafbb0e1"
+ },
+ "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4ccd31891378d2025ef58980481608f11f5b35a988e877652e7cbb0a6127287c"
+ },
+ "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdef989cb85107747de11222bd7418411f8f3264855e1939ef6bef9447e42076d"
+ },
+ "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb7c2ef96238f635f86f9950700e36368efaaa70e764865dddc43ff6e96f6b346"
+ },
+ "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x92b13a73440c6421da22e848d23f9af80610085ab05662437d850c97a012d8d3"
+ },
+ "0xb55a3d332d267493105927b892545d2cd4c83bd6": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc781c7c3babeb06adfe8f09ecb61dbe0eb671e41f3a1163faac82fdfa2bc83e8"
+ },
+ "0xb609bc528052bd9669595a35f6eb6a4d7a30ac3d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6388bfcbbd6000e90a10633c72c43b0b0fed7cf38eab785a71e6f0c5b80a26a"
+ },
+ "0xb68176634dde4d9402ecb148265db047d17cb4ab": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf4a1c4554b186a354b3e0c467eef03df9907cd5a5d96086c1a542b9e5160ca78"
+ },
+ "0xb70654fead634e1ede4518ef34872c9d4f083a53": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7f9726a7b2f5f3a501b2d7b18ec726f25f22c86348fae0f459d882ec5fd7d0c7"
+ },
+ "0xb71de80778f2783383f5d5a3028af84eab2f18a4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x64d0de66ea29cbcf7f237dae1c5f883fa6ff0ba52b90f696bb0348224dbc82ce"
+ },
+ "0xb787c848479278cfdb56950cda545cd45881722d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1098f06082dc467088ecedb143f9464ebb02f19dc10bd7491b03ba68d751ce45"
+ },
+ "0xb911abeead298d03c21c6c5ff397cd80eb375d73": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x54abcdbc8b04bc9b70e9bd46cb9db9b8eb08cfd4addba4c941dacc34dd28648e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000054": "54",
+ "0x0000000000000000000000000000000000000000000000000000000000000055": "55",
+ "0x0000000000000000000000000000000000000000000000000000000000000056": "56"
+ },
+ "key": "0x873429def7829ff8227e4ef554591291907892fc8f3a1a0667dada3dc2a3eb84"
+ },
+ "0xb917b7f3d49770d3d2f0ad2f497e5bfe0f25dc5f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x11d4eec7df52cd54e74690a487884e56371976c2b8c49ffc4c8f34831166bf4e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000162": "0162",
+ "0x0000000000000000000000000000000000000000000000000000000000000163": "0163",
+ "0x0000000000000000000000000000000000000000000000000000000000000164": "0164"
+ },
+ "key": "0x65e6b6521e4f1f97e80710581f42063392c9b33e0aeea4081a102a32238992ea"
+ },
+ "0xb9b85616fc8ed95979a5e31b8968847e7518b165": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6a5e43139d88da6cfba857e458ae0b5359c3fde36e362b6e5f782a90ce351f14"
+ },
+ "0xbac9d93678c9b032c393a23e4c013e37641ad850": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8a8266874b43f78d4097f27b2842132faed7e7e430469eec7354541eb97c3ea0"
+ },
+ "0xbbeebd879e1dff6918546dc0c179fdde505f2a21": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x170c927130fe8f1db3ae682c22b57f33f54eb987a7902ec251fe5dba358a2b25"
+ },
+ "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe74ac72f03e8c514c2c75f3c4f54ba31e920374ea7744ef1c33937e64c7d54f1"
+ },
+ "0xbc5959f43bc6e47175374b6716e53c9a7d72c594": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfd3a8bacd3b2061cbe54f8d38cf13c5c87a92816937683652886dee936dfae10"
+ },
+ "0xbceef655b5a034911f1c3718ce056531b45ef03b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6c05d8abc81143ce7c7568c98aadfe6561635c049c07b2b4bce3019cef328cb9"
+ },
+ "0xbd079b0337a29cccd2ec95b395ef5c01e992b6a5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf0877d51b7712e08f2a3c96cddf50ff61b8b90f80b8b9817ea613a8a157b0c45"
+ },
+ "0xbe3eea9a483308cb3134ce068e77b56e7c25af19": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7026c939a9158beedff127a64f07a98b328c3d1770690437afdb21c34560fc57"
+ },
+ "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x72d91596112f9d7e61d09ffa7575f3587ad9636172ae09641882761cc369ecc0"
+ },
+ "0xc18d2be47547904f88a4f46cee75f8f4a94e1807": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9c32ffd5059115bba9aed9174f5ab8b4352e3f51a85dde33000f703c9b9fe7c2",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000018a": "018a",
+ "0x000000000000000000000000000000000000000000000000000000000000018b": "018b",
+ "0x000000000000000000000000000000000000000000000000000000000000018c": "018c"
+ },
+ "key": "0xa601eb611972ca80636bc39087a1dae7be5a189b94bda392f84d6ce0d3c866b9"
+ },
+ "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99dba7e9230d5151cc37ff592fa1592f27c7c81d203760dfaf62ddc9f3a6b8fd"
+ },
+ "0xc305dd6cfc073cfe5e194fc817536c419410a27d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x016d92531f4754834b0502de5b0342ceff21cde5bef386a83d2292f4445782c2"
+ },
+ "0xc337ded6f56c07205fb7b391654d7d463c9e0c72": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c608293e741d1eb5ae6916c249a87b6540cf0c2369e96d293b1a7b5b9bd8b31"
+ },
+ "0xc57aa6a4279377063b17c554d3e33a3490e67a9a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc192ea2d2bb89e9bb7f17f3a282ebe8d1dd672355b5555f516b99b91799b01f6"
+ },
+ "0xc5eaec262d853fbdaccca406cdcada6fa6dd0944": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x471bf8988ad0d7602d6bd5493c08733096c116ac788b76f22a682bc4558e3aa7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000158": "0158",
+ "0x0000000000000000000000000000000000000000000000000000000000000159": "0159",
+ "0x000000000000000000000000000000000000000000000000000000000000015a": "015a"
+ },
+ "key": "0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3"
+ },
+ "0xc7a0a19ea8fc63cc6021af2e11ac0584d75c97b7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe2a164e2c30cf30391c88ff32a0e202194b08f2a61a9cd2927ea5ed6dfbf1056",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000e5": "e5",
+ "0x00000000000000000000000000000000000000000000000000000000000000e6": "e6",
+ "0x00000000000000000000000000000000000000000000000000000000000000e7": "e7"
+ },
+ "key": "0x86d03d0f6bed220d046a4712ec4f451583b276df1aed33f96495d22569dc3485"
+ },
+ "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8e11480987056c309d7064ebbd887f086d815353cdbaadb796891ed25f8dcf61"
+ },
+ "0xc7d4ef05550c226c50cf0d4231ba1566d03fa98d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3a2985c6ada67e5604b99fa2fc1a302abd0dc241ee7f14c428fa67d476868bb6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000010d": "010d",
+ "0x000000000000000000000000000000000000000000000000000000000000010e": "010e",
+ "0x000000000000000000000000000000000000000000000000000000000000010f": "010f"
+ },
+ "key": "0x5a356862c79afffd6a01af752d950e11490146e4d86dfb8ab1531e9aef4945a1"
+ },
+ "0xca358758f6d27e6cf45272937977a748fd88391d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbccd3d2f920dfb8d70a38c9ccd5ed68c2ef6e3372199381767ce222f13f36c87"
+ },
+ "0xca87240ef598bd6e4b8f67b3761af07d5f575514": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x11f5d399ca8fb7a9af5ad481be60cf61d45493cd20206c9d0a237ce7d7571e5f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001f3": "01f3",
+ "0x00000000000000000000000000000000000000000000000000000000000001f4": "01f4",
+ "0x00000000000000000000000000000000000000000000000000000000000001f5": "01f5"
+ },
+ "key": "0x4b238e08b80378d0815e109f350a08e5d41ec4094df2cfce7bc8b9e3115bda70"
+ },
+ "0xcb925b74da97bdff2130523c2a788d4beff7b3c3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe0c5acf66bda927704953fdf7fb4b99e116857121c069eca7fb9bd8acfc25434"
+ },
+ "0xcccc369c5141675a9e9b1925164f30cdd60992dc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe2511e8a33ac9973b773aaedcb4daa73ae82481fe5a1bf78b41281924260cf5"
+ },
+ "0xce24f30695b735e48b67467d76f5185ee3c7a0c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5442e0279d3f1149de4ce8d9e2d3f01d1854755038ac1a0fae5c48749bf71f20",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001e9": "01e9",
+ "0x00000000000000000000000000000000000000000000000000000000000001ea": "01ea",
+ "0x00000000000000000000000000000000000000000000000000000000000001eb": "01eb"
+ },
+ "key": "0x47450e5beefbd5e3a3f80cbbac474bb3db98d5e609aa8d15485c3f0d733dea3a"
+ },
+ "0xd048d242574c45095c72eaf58d2808778117afcb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x7217cb747054306f826e78aa3fc68fe4441299a337ecea1d62582f2da8a7f336",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001a8": "01a8",
+ "0x00000000000000000000000000000000000000000000000000000000000001a9": "01a9",
+ "0x00000000000000000000000000000000000000000000000000000000000001aa": "01aa"
+ },
+ "key": "0xa9656c0192bb27f0ef3f93ecc6cc990dd146da97ac11f3d8d0899fba68d5749a"
+ },
+ "0xd0752b60adb148ca0b3b4d2591874e2dabd34637": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x625e5c85d5f4b6385574b572709d0f704b097527a251b7c658c0c4441aef2af6"
+ },
+ "0xd089c853b406be547d8e331d31cbd5c4d472a349": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x389093badcaa24c3a8cbb4461f262fba44c4f178a162664087924e85f3d55710"
+ },
+ "0xd0918e2e24c5ddc0557a61ca11e055d2ac210fe5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x25b42ec5480843a0328c63bc50eff8595d90f1d1b0afcab2f4a19b888c794f37",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000a9": "a9",
+ "0x00000000000000000000000000000000000000000000000000000000000000aa": "aa",
+ "0x00000000000000000000000000000000000000000000000000000000000000ab": "ab"
+ },
+ "key": "0xbaae09901e990935de19456ac6a6c8bc1e339d0b80ca129b8622d989b5c79120"
+ },
+ "0xd10b36aa74a59bcf4a88185837f658afaf3646ef": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9fe8b6e43098a4df56e206d479c06480801485dfd8ec3da4ccc3cebf5fba89a1"
+ },
+ "0xd1211001882d2ce16a8553e449b6c8b7f71e6183": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x61088707d2910974000e63c2d1a376f4480ba19dde19c4e6a757aeb3d62d5439"
+ },
+ "0xd1347bfa3d09ec56b821e17c905605cd5225069f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x287acc7869421fb9f49a3549b902fb01b7accc032243bd7e1accd8965d95d915",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000019e": "019e",
+ "0x000000000000000000000000000000000000000000000000000000000000019f": "019f",
+ "0x00000000000000000000000000000000000000000000000000000000000001a0": "01a0"
+ },
+ "key": "0x5b90bb05df9514b2d8e3a8feb3d6c8c22526b02398f289b42111426edc4fe6cf"
+ },
+ "0xd20b702303d7d7c8afe50344d66a8a711bae1425": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4d67d989fdb264fa4b2524d306f7b3f70ddce0b723411581d1740407da325462"
+ },
+ "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0e27113c09de0a0cb0ff268c677aba17d39a3190fe15aec0ff7f54184955cba4"
+ },
+ "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x79afb7a5ffe6ccd537f9adff8287b78f75c37d97ea8a4dd504a08bc09926c3fa"
+ },
+ "0xd39b94587711196640659ec81855bcf397e419ff": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9de128e7d4347403eb97f45e969cd1882dfe22c1abe8857aab3af6d0f9e9b92"
+ },
+ "0xd48171b7166f5e467abcba12698df579328e637d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x188111c233bf6516bb9da8b5c4c31809a42e8604cd0158d933435cfd8e06e413"
+ },
+ "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1068e9986da7636501d8893f67aa94f5d73df849feab36505fd990e2d6240e9"
+ },
+ "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe5302e42ca6111d3515cbbb2225265077da41d997f069a6c492fa3fcb0fdf284"
+ },
+ "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9a1896e612ca43ecb7601990af0c3bc135b9012c50d132769dfb75d0038cc3be"
+ },
+ "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfc4870c3cd21d694424c88f0f31f75b2426e1530fdea26a14031ccf9baed84c4"
+ },
+ "0xd917458e88a37b9ae35f72d4cc315ef2020b2418": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4c2765139cace1d217e238cc7ccfbb751ef200e0eae7ec244e77f37e92dfaee5"
+ },
+ "0xdbe726e81a7221a385e007ef9e834a975a4b528c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5fcd9b6fce3394ad1d44733056b3e5f6306240974a16f9de8e96ebdd14ae06b1"
+ },
+ "0xdc60d4434411b2608150f68c4c1b818b6208acc2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x27e9b6a54cf0fb188499c508bd96d450946cd6ba1cf76cf5343b5c74450f6690",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001df": "01df",
+ "0x00000000000000000000000000000000000000000000000000000000000001e0": "01e0",
+ "0x00000000000000000000000000000000000000000000000000000000000001e1": "01e1"
+ },
+ "key": "0x8510660ad5e3d35a30d4fb7c2615c040f9f698faae2ac48022e366deaeecbe77"
+ },
+ "0xdd1e2826c0124a6d4f7397a5a71f633928926c06": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf0a51b55aadfa3cafdd214b0676816e574931a683f51218207c625375884e785"
+ },
+ "0xdd9ee108e8d5d2e8937e9fd029ec3a6640708af0": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x8289b558865f2ca1f54c98b5ff5df95f07c24ec605e247b58c7798605dcd794f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001cb": "01cb",
+ "0x00000000000000000000000000000000000000000000000000000000000001cc": "01cc",
+ "0x00000000000000000000000000000000000000000000000000000000000001cd": "01cd"
+ },
+ "key": "0x2a39afbe88f572c23c90da2d059af3de125f1da5c3753c530dc5619a4857119f"
+ },
+ "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbb861b82d884a70666afeb78bbf30cab7fdccf838f4d5ce5f4e5ca1be6be61b1"
+ },
+ "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9966a8b4cd856b175855258fa7e412ffef06d9e92b519050fa7ac06d8952ac84"
+ },
+ "0xdfe052578c96df94fa617102199e66110181ed2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x54c12444ede3e2567dd7f4d9a06d4db8c6ab800d5b3863f8ff22a0db6d09bf24"
+ },
+ "0xe3a71b4caf54df7d2480743c5a6770a1a5a9bcda": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe4d9c31cc9b4a9050bbbf77cc08ac26d134253dcb6fd994275c5c3468f5b7810"
+ },
+ "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x70aae390a762a4347a4d167a2431874554edf1d77579213e55fea3ec39a1257c"
+ },
+ "0xe439e4ea04e52cf38d0925f0722d341097378b88": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x6c00e091dae3d4226facd6be802c865d5db0f524754d22666406138b54fab0e6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000008b": "8b",
+ "0x000000000000000000000000000000000000000000000000000000000000008c": "8c",
+ "0x000000000000000000000000000000000000000000000000000000000000008d": "8d"
+ },
+ "key": "0x38152bce526b7e1c2bedfc9d297250fcead02818be7806638564377af145103b"
+ },
+ "0xe43ce33cdb88a2efe8a3d652bfb252fd91a950a7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc157e0d637d64b90e2c59bc8bed2acd75696ea1ac6b633661c12ce8f2bce0d62"
+ },
+ "0xe52c0f008957444c48eba77467eaf2b7c127e3c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb888c9946a84be90a9e77539b5ac68a3c459761950a460f3e671b708bb39c41f"
+ },
+ "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x519abb269c3c5710f1979ca84192e020ba5c838bdd267b2d07436a187f171232"
+ },
+ "0xe6dddbffde545e58030d4b8ca9e00cfb68975b5d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2afe93e1b0f26e588d2809127e4360ad7e28cf552498b2bc4847d6bcda738cdb",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000130": "0130",
+ "0x0000000000000000000000000000000000000000000000000000000000000131": "0131",
+ "0x0000000000000000000000000000000000000000000000000000000000000132": "0132"
+ },
+ "key": "0xa0f5dc2d18608f8e522ffffd86828e3d792b36d924d5505c614383ddff9be2eb"
+ },
+ "0xe75db02929f3d5d7c28ecdb064ece929602c06bd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9eda8eb6ca03d7c4afe47279acc90a45d1b2ca6a11afd95206f8868d20520d06",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000001e": "1e",
+ "0x000000000000000000000000000000000000000000000000000000000000001f": "1f",
+ "0x0000000000000000000000000000000000000000000000000000000000000020": "20"
+ },
+ "key": "0x600a7a5f41a67f6f759dcb664198f1c5d9b657fb51a870ce9e234e686dff008e"
+ },
+ "0xe7b2ceb8674516c4aeb43979808b237656ab3b6b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcd31ed5d5da79990afed0d993cb725c4e34dd97544b03466ed34212e42c28d68",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000014e": "014e",
+ "0x000000000000000000000000000000000000000000000000000000000000014f": "014f",
+ "0x0000000000000000000000000000000000000000000000000000000000000150": "0150"
+ },
+ "key": "0x75d231f57a1a9751f58769d5691f4807ab31ac0e802b1a1f6bfc77f5dff0adbf"
+ },
+ "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xec3e92967d10ac66eff64a5697258b8acf87e661962b2938a0edcd78788f360d"
+ },
+ "0xe82c38488eded9fb72a5ed9e039404c537f20b13": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7a2464bc24d90557940e93a3b73308ea354ed7d988be720c545974a17959f93f"
+ },
+ "0xe920ab4e34595482e98b2c0d16be164c49190546": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd623b1845175b206c127c08046281c013e4a3316402a771f1b3b77a9831143f5"
+ },
+ "0xe99c76a6c3b831a926ab623476d2ec14560c09b4": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x0fd8e99b1b4ab4eb8c6c2218221ae6978cc67433341ed8a1ad6185d34fa82c61",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "14",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "15",
+ "0x0000000000000000000000000000000000000000000000000000000000000016": "16"
+ },
+ "key": "0x6641e3ed1f264cf275b53bb7012dabecf4c1fca700e3db989e314c24cc167074"
+ },
+ "0xe9b17e54dba3344a23160cb2b64f88024648c53e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb4f179efc346197df9c3a1cb3e95ea743ddde97c27b31ad472d352dba09ee1f5"
+ },
+ "0xebe708edc62858621542b7354bb478228eb95577": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7bff1b6b56891e66584ced453d09450c2fed9453b1644e8509bef9f9dd081bbb"
+ },
+ "0xebf37af41b6d7913aed3b9cc650d1e8f58a3d785": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x209b102e507b8dfc6acfe2cf55f4133b9209357af679a6d507e6ee87112bfe10"
+ },
+ "0xeda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xabd8afe9fbf5eaa36c506d7c8a2d48a35d013472f8182816be9c833be35e50da"
+ },
+ "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xce732a5e3b88ae26790aeb390a2bc02c449fdf57665c6d2c2b0dbce338c4377e"
+ },
+ "0xf031efa58744e97a34555ca98621d4e8a52ceb5f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x00748bacab20da9ae19dd26a33bd10bbf825e28b3de84fc8fe1d15a21645067f"
+ },
+ "0xf068ae4089a66c79afe47d6e513f718838d8f73f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x72c89221daedccdd3fbba66c1b081b3634ce89d5a069be97ff7832778f7b023a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000003c": "3c",
+ "0x000000000000000000000000000000000000000000000000000000000000003d": "3d",
+ "0x000000000000000000000000000000000000000000000000000000000000003e": "3e"
+ },
+ "key": "0x37310559ceaade42e45b3e3f05925aadca9e60aeeb9dd60d824875d9e9e71e26"
+ },
+ "0xf0a279d2276de583ebcd7f69a6532f13349ad656": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x11eb0304c1baa92e67239f6947cb93e485a7db05e2b477e1167a8960458fa8cc"
+ },
+ "0xf0a5f15ef71424b5d543394ec46c46bfd2817747": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xbefe55b606a865c3898ec2093bd160b37c3976011516f43736cac2a9a7ecd4ca",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000e0": "e0",
+ "0x00000000000000000000000000000000000000000000000000000000000000e1": "e1",
+ "0x00000000000000000000000000000000000000000000000000000000000000e2": "e2"
+ },
+ "key": "0xdbea1fd70fe1c93dfef412ce5d8565d87d6843aac044d3a015fc3db4d20a351b"
+ },
+ "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xabdc44a9bc7ccf1ce76b942d25cd9d731425cd04989597d7a2e36423e2dac7ee"
+ },
+ "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x728325587fa336e318b54298e1701d246c4f90d6094eb95635d8a47f080f4603"
+ },
+ "0xf1fc98c0060f0d12ae263986be65770e2ae42eae": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xca7ad42d3c4fe14ddb81bf27d4679725a1f6c3f23b688681bb6f24262d63212f"
+ },
+ "0xf4f97c88c409dcf3789b5b518da3f7d266c48806": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x84c7ee50e102d0abf5750e781c1635d60346f20ab0d5e5f9830db1a592c658ff"
+ },
+ "0xf5347043ae5fca9412ca2c72aee17a1d3ba37691": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xf390264acaf1433c0ea670b2c094a30076641469524ae24f5fddc44e99c5b032",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000004f": "4f",
+ "0x0000000000000000000000000000000000000000000000000000000000000050": "50",
+ "0x0000000000000000000000000000000000000000000000000000000000000051": "51"
+ },
+ "key": "0xa5541b637a896d30688a80b7affda987d9597aac7ccd9799c15999a1d7d094e2"
+ },
+ "0xf57fd44ccea35d9c530ef23f3e55de2f6e5415bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6d4162ce16817e46fa2ddc5e70cee790b80abc3d6f7778cfbaed327c5d2af36c"
+ },
+ "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7e839d9fd8a767e90a8b2f48a571f111dd2451bc5910cf2bf3ae79963e47e34d"
+ },
+ "0xf61ac2a10b7981a12822e3e48671ebd969bce9c2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbfe5dee42bddd2860a8ebbcdd09f9c52a588ba38659cf5e74b07d20f396e04d4"
+ },
+ "0xf7eaadcf76ffcf006a86deb2f17d0b8fe0b211a8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1dff76635b74ddba16bba3054cc568eed2571ea6becaabd0592b980463f157e2"
+ },
+ "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x662d147a16d7c23a2ba6d3940133e65044a90985e26207501bfca9ae47a2468c"
+ },
+ "0xf8d20e598df20877e4d826246fc31ffb4615cbc0": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa248850a2e0d6fe62259d33fc498203389fa754c3bd098163e86946888e455bd"
+ },
+ "0xf91193b7442e274125c63003ee53f4ce5836f424": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xb25f9e4f6f913a4a1e8debf7d4752bfa521d147bb67c69d5855301e76dd80633",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001d5": "01d5",
+ "0x00000000000000000000000000000000000000000000000000000000000001d6": "01d6",
+ "0x00000000000000000000000000000000000000000000000000000000000001d7": "01d7"
+ },
+ "key": "0xbfe731f071443795cef55325f32e6e03c8c0d0398671548dfd5bc96b5a6555c0"
+ },
+ "0xf997ed224012b1323eb2a6a0c0044a956c6b8070": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbcebc35bfc663ecd6d4410ee2363e5b7741ee953c7d3359aa585095e503d20c8"
+ },
+ "0xfb7b49bc3178263f3a205349c0e8060f44584500": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa03fe040e4264070290e95ffe06bf9da0006556091f17c5df5abaa041de0c2f7"
+ },
+ "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf63360f8bb23f88b0a564f9e07631c38c73b4074ba4192d6131336ef02ee9cf2"
+ },
+ "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd3443fa37ee617edc09a9c930be4873c21af2c47c99601d5e20483ce6d01960a"
+ },
+ "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1c248f110218eaae2feb51bc82e9dcc2844bf93b88172c52afcb86383d262323"
+ },
+ "0xfde502858306c235a3121e42326b53228b7ef469": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe3d7213321be060ae2e1ff70871131ab3e4c9f4214a17fe9441453745c29365b"
+ },
+ "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe31747e6542bf4351087edfbeb23e225e4217b5fa25d385f33cd024df0c9ae12"
+ },
+ "0xfe96089d9b79f2d10f3e8b0fb9629aeb6cc7cde6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcf2123d110997f426821d3e541334e43fdd6b5286c3c33252c24b5f8aafc7aa2",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001d0": "01d0",
+ "0x00000000000000000000000000000000000000000000000000000000000001d1": "01d1",
+ "0x00000000000000000000000000000000000000000000000000000000000001d2": "01d2"
+ },
+ "key": "0xbf632670b6fa18a8ad174a36180202bfef9a92c2eeda55412460491ae0f6a969"
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/newpayload.json b/cmd/devp2p/internal/ethtest/testdata/newpayload.json
new file mode 100644
index 0000000000..7f8c99afa9
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/newpayload.json
@@ -0,0 +1,13268 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": "np72",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x9e8a444b740df016941ecc815fe9eebeaa04a047db6569855573a52a8cb78cdd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x74035b613e4ea1072fd029f35d0fa5b26fbfaa54cabebcec88b9ee07cca321ae",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x48",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x2d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x568d2f9",
+ "blockHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809",
+ "transactions": [
+ "0xf86a39840568d2fa8252089444bd7ae60f478fae1061e11a7739f4b94d1daf9101808718e5bb3abd10a0a050fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125ca04f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np73",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18b68edcdfc835d5db51310e7960eaf0c0afcc5a6611282d2085f3282b2f9e3f",
+ "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x49",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146e8",
+ "timestamp": "0x2da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4bbd14a",
+ "blockHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b",
+ "transactions": [
+ "0xf8853a8404bbd14b830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a027748abc264040530bca00d1cc86b199586c1fe26955cd5e250b97e2b9ca3128a050a822d9df3b63e6911766d4ae8c722f5afee7a6c06a7b5eb73772a5b137ca36"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np74",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fb7295e0a62bff03ddeba56ba643cd817fab6bc8df11309f8e8a3dbcf7d502e",
+ "receiptsRoot": "0x7b9d8080a095524251324dc00e77d3ecf4c249c48eebed2e4a5acedc678c70b4",
+ "logsBloom": "0x000800000000000000000000000000000900000000000000000000000000c0080000000000000010000000020000000000000004100000000480008020100000000000000000000000000000001000200000000000000010000010000000000000000000000000000000000000000000000000000000000200000000000000800001000000000000000000000000000000000004000000000000000800000000008000000000000001000000000002000000000000000000000000000000080000000000000000200404000000000000000000000000000000000000000000000000080100000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc61",
+ "timestamp": "0x2e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x424ad37",
+ "blockHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13",
+ "transactions": [
+ "0xf87c3b840424ad3883011f548080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a050e3677064fe82b08a8fae8cea250fbaf00dbca1b6921cffd311ca17c7979865a051e738138eab4b31f1ba163b8ed2cfd778af98eff583cd5a26fcd9bd673fe027"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np75",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x65038690e44bf1ee49d47beb6efc7cc84d7f01d2ba645768e3a584a50979b36d",
+ "receiptsRoot": "0xf5419129ce2f36d1b2206d4723f3e499691ad9aee741223426cda1b22e601a19",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36c",
+ "timestamp": "0x2ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3a051bc",
+ "blockHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61",
+ "transactions": [
+ "0xf8673c8403a051bd83020888808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0dd01417c1ac62f9e593b07848f93c1f5ab729e73a493e22141f6e1c6e8a4f94fa00b9e979c6bae8ab4a90b7b2ba61d590d800e5411bc12be320efc3fb7310506e3"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np76",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b8d5706f2e3d66bb968de876e2683d75dce76d04118bc0184d6af44fb10196f",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x2f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x32ca5cf",
+ "blockHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766",
+ "transactions": [
+ "0x02f86d870c72dd9d5e883e3d0184032ca5d08252089472dfcfb0c470ac255cde83fb8fe38de8a128188e0180c080a0116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36a017001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np77",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b8d17721b733ce2b6e7607a69fb6bf678dbabcb708f64cb5d211915b3238090",
+ "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146e8",
+ "timestamp": "0x302",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2c71f92",
+ "blockHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e",
+ "transactions": [
+ "0xf8853e8402c71f93830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00cb7fb1bba811ea1948e035550c66840f0491d29d0ae9a6e4726e77a57ca8058a041523fc7133a6473784720a68d7f7f1d54d8a5a1f868640783a0284fb22f4309"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np78",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf21b9b380d6c5833270617a17ea187e1f85a6556f1c1dfaf6bcb0700c88abe24",
+ "receiptsRoot": "0xb08f0ccb7116304320035e77c514c9234f2d5a916d68de82ba20f0a24ab6d9e4",
+ "logsBloom": "0x00000000000000400000000000200000000000000000000000000000000000000000200010000000000000000000000000000040000400000010000000000020000000000000000000000000000000000000000000000000000000900000000000800000000800000010000008000000000000000000000102000000000000100000080000000100000000000000000000000000000008000000000000008000800800000000000000000000400000000008200000000200200000000000000000000000000000200000000000000000000000000000000000000000000000000000000011000000000000800000000000000000000000000000000000000008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x30c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x26e6e24",
+ "blockHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c",
+ "transactions": [
+ "0xf87c3f84026e6e2583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1ba7a3639ec15944466d72a2e972d5eda143fc54f07aa47ecd56769ba5fbf8a041018f9af7a55685cbfa25d35f353e4bccef32a5e0bcdb373191d34cfed9a8db"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np79",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8bb2c279cf46bd7eb856cc00fdce9bb396b21f65da47fdf0f13b41e0c0e0aa7f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x316",
+ "extraData": "0x",
+ "baseFeePerGas": "0x220c283",
+ "blockHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619",
+ "transactions": [
+ "0xf86740840220c2848302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bcd36ef6498fd3ce093febc53b3e35004a9d9200816306515f5ffad98140426fa00656b7e75310845c1d2e47495ed7765d687f0a943a604644d9cf7b97b01f300f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np80",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x62b57c9d164c28bc924ec89b1fe49adc736ee45e171f759f697899a766e3f7a4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x50",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x320",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1dce188",
+ "blockHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb",
+ "transactions": [
+ "0xf869418401dce189825208945c62e091b8c0565f1bafad0dad5934276143ae2c01808718e5bb3abd10a0a0b82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d59fdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np81",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1820989c0844509c8b60af1baa9030bdcc357bc9462b8612493af9d17c76eb3d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x51",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x32a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1a14dd8",
+ "blockHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x5",
+ "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np82",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8145365a52eb3a4b608966d28a8ed05598c13af426c7ab24f28f2bdc7a00b12b",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x52",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x334",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16d241d",
+ "blockHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62",
+ "transactions": [
+ "0xf8854284016d241e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a061c5ecaf5f73e89370f5b35c31bce60d04c7417cc70cc897beae6429cb6d3880a02271644378271ec296459da5181507d52bdbd4489600690c32998cdb4b032042"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np83",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x07cc0bca2e8f3b243635dc6f988372dd2427b6090f1035d06f2eff2e99315170",
+ "receiptsRoot": "0xace7ae7e3c226cecca4b33082b19cd1023960138a576ef77fddadcc223b4250a",
+ "logsBloom": "0x40000010010000000000000100000c00000001000000000000000000000000000000000200000000000042000000000000001000000000000000000000000000000000000000000000000820040000800000000000004000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000800000001000000000000000000000000000000000000000004000004000000000000000410000000000000000000000040000000000000000004000000000000000000000000000400001000000000000000000400000000000000000000200080000000000000000000000010000000040000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x53",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x33e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x13f998a",
+ "blockHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721",
+ "transactions": [
+ "0xf87c4384013f998b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a01001f6f02c9dac33915eb5d0fe81d88599a29341d84ee6f46b1ef05d270a0c1fa05ea1dbc664d9f4a83b4743bc40579e6b727ff8b5e78c4249bd59aa47c33d770f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np84",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1a71059650ccefaf7d0a407c43a87ccc9fe63a6369a46509074658f714c54ad",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x54",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x348",
+ "extraData": "0x",
+ "baseFeePerGas": "0x117b7e1",
+ "blockHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84",
+ "transactions": [
+ "0xf86744840117b7e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b4a7e6c791f457a428f870b8df8ee0148acac74050aeea658c3dad552a7e8140a0793951ba22a6f628dd86ec8964b09c74e0f77306a28dd276dfe42f40ee76c73c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np85",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x198575d6df4370febe3a96865e4a2280a5caa2f7bd55058b27ea5f3082db8d99",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x55",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x352",
+ "extraData": "0x",
+ "baseFeePerGas": "0xf4dd4f",
+ "blockHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e450183f4dd5082520894a25513c7e0f6eaa80a3337ee18081b9e2ed09e000180c080a0e8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8a07c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np86",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x90c402a8569aae0c095540a9762aefac4f43df4e97fc7a24df1d4051c555bc2c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x56",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x35c",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd64603",
+ "blockHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1",
+ "validatorIndex": "0x5",
+ "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np87",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e1765cf5abdf835814ee20c9e401b0e99e2b31f2ad8ea14c62ef732c6e63d2d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x57",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x366",
+ "extraData": "0x",
+ "baseFeePerGas": "0xbb7d43",
+ "blockHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04",
+ "transactions": [
+ "0xf8844683bb7d44830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a052c928a2062b214d44b9a641faf87e439fbc5a07f571021f0f3c8fd2a2087a57a0650c77ab1cd522a7d3a435058f53636b6ae86d19fd4f691bf61c13fd8b7de69a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np88",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ec8183c28814317cb7a7b86633041db40de94b45a47dab5614b21087c308648",
+ "receiptsRoot": "0xe2e7a47b1c0009f35c3a46c96e604a459822fe9f02929afa823f2c514f1fbd39",
+ "logsBloom": "0x00000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000200000000008000000000000000000000000000000800000000000000800000000000000000000002000000000100000000000000000000000000000000000000001000000000400000000000000000000000000000000001000000000000000000000000000000000000000000000020000000000000400000000000000100000000000100000000000000000000100200000000000000000000000000000010400000000000000050080004000000400000000010000000800030001000000000000000004000000000000000000a00",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x58",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x370",
+ "extraData": "0x",
+ "baseFeePerGas": "0xa41aed",
+ "blockHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849",
+ "transactions": [
+ "0xf87b4783a41aee83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09799e22509fcf203235570e7ba0df80bad6124b89b812146b50bca27f03161a9a0118a4f264815d7cf1a069009bff736f04369e19e364bd1a409a4c4865ec7d81f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np89",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x07118ca8999c49a924f92b54d21cecad7cbcc27401d16181bbcdee05b613399c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x59",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x37a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8fa090",
+ "blockHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18",
+ "transactions": [
+ "0xf86648838fa0918302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd5a86a96cbf94d2bba5c7fb6efd2bf501dd30c8b37e896ae360b40ab693272aa0331e570a5b3ce2cef67731c331bba3e6de2ede8145dd0719ce6dfcca587c64ba"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np90",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d9d080dde44cc511dc9dc457b9839409e1b3a186e6b9a5ae642b5354acc6cc4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x384",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7dbb15",
+ "blockHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9",
+ "transactions": [
+ "0xf86949837dbb1682520894bbeebd879e1dff6918546dc0c179fdde505f2a2101808718e5bb3abd10a0a002f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849a0182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np91",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5aea2e2c617a5a3a341e01c72fbf960e809dd589b4a988a04d50f6fb666b6c8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x38e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6e05f1",
+ "blockHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2",
+ "validatorIndex": "0x5",
+ "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np92",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd1e927e1a7106591aa46d3e327e9e7d493248786b4c6284bd138d329c6cb1fbb",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x398",
+ "extraData": "0x",
+ "baseFeePerGas": "0x604533",
+ "blockHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f",
+ "transactions": [
+ "0xf8844a83604534830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0667955bfddc6500ad6a0a298d08a0fdeb453d483be41f7496f557039c99d5b8ea06ad5f6871f3d78ea543484d51590454f8a65b5b1b89f58992ff94a02a30c0c93"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np93",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d4e68f0a1ad7578b1627d665263c04856efa4eb4938014a8c794547d597f89b",
+ "receiptsRoot": "0xa37a62134a71ef21b16f2eee431b806a4d13c0a80a11ddeb5cbb18e3707aecdf",
+ "logsBloom": "0x00000000000000000000000002000000000021000000000000000000240000000000000000000000000004000000010000000000000000000000000000000000000008000000000000000000000000000020000000000000000400000400000000000400000000000000000000000000000000000080000004000000000000000000000000000800000000000000000000000000000000000000000000002000000080000002010000420000000000000000000000000040402002000200000000000000000000000000008000000000000000000000000100000000000000000000000000000000000084000000000080000000000000000000040000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x3a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x544364",
+ "blockHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b",
+ "transactions": [
+ "0xf87b4b8354436583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09662003f67b0c146ecaa0c074b010d1f27d0803dc1809fd4f6ea80a5f09c34aea0100a5c0fbfdbee733f1baecb893a33ce2d42316303a5ddf1515645dfbb40d103"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np94",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd07ab096fc1b3e50229bcff0fc5fca9e9f7d368e77fe43a71e468b7b0adb133",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x3ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x49bf97",
+ "blockHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80",
+ "transactions": [
+ "0xf8664c8349bf988302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa03b3113a7b1919311fbc03ee25c4829b60f07341c72107de061da06eef7ec0856a01bc4eeb29301e1610984ee042f8236863ad78402d3d55c69a6922d67238dde75"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np95",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4a154c665e5b68adadf9455bd905da607f0279b5d2b4bfb0c1a3db5b6a908d4d",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x3b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x408f22",
+ "blockHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np96",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b2adb11488a7634a20bc6f81bcc0211993fe790f75eeb1f4889a98d1bdbcb37",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x60",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x3c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x387e65",
+ "blockHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3",
+ "validatorIndex": "0x5",
+ "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np97",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd67c810501ca4f4ee4262e86dcaf793ca75637249bf157dee4800274372f236f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x61",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x3ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x316e99",
+ "blockHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf",
+ "transactions": [
+ "0xf8844e83316e9a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a036b2adb5bbd4d43198587067bf0b669e00862b0807adb947ee4c9869d79f9d8ca063e0b200645435853dceed29fd3b4c55d94b868a0aa6513ca6bd730705f2c9ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np98",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xae82dda9df38bcc8d99e311b63ae055591953577b6b560840658eca24ecacee9",
+ "receiptsRoot": "0x675ab823f90b9bdd3d04afb108bc1a1dcd77654a0de4c8a539e355b6d24f29f4",
+ "logsBloom": "0x10000000000000000010000000000020000000000008000000000000000000000000000000000000000000020000000000000000000000000000040000010000000000000000000000000000000000000000000000008000000000000000000000000080000110000000000800000002000000800040800000000040000000000000004000000000001000000000000000000000000000000000008000000000000000000000000000000020010080001000000000000000000000000004008000004000008000000000000000040000000400000000000001000000000000000000000008000000000000000000000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x62",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x3d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2b4449",
+ "blockHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517",
+ "transactions": [
+ "0xf87b4f832b444a83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0824522ae97a912dd75a883798f4f296d960f6a7be8510e2a4a121d85f496da16a008cade93390e31f7b0e6615b4defe3bd4225b7a4d97a7835c02ad0b4d004fb5b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np99",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x588419f24b32499745bbae81eb1a303d563c31b2743c8621d39b820c2affb3cb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x63",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x3de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x25de20",
+ "blockHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962",
+ "transactions": [
+ "0xf866508325de218302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0744b7f5fb26cc6dd16b1849d0c04236e3b4e993f37e5b91de6e55f5f899450baa0456225c91372bddd4e3a1dde449e59ad62d63f0c850f9b869870ea2621494fd7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np100",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfee7a27147c7984caec35dc4cee4f3a38fee046e5d8f17ce7ec82b982decd9aa",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x64",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x3e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x212635",
+ "blockHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e",
+ "transactions": [
+ "0xf86951832126368252089418ac3e7343f016890c510e93f935261169d9e3f501808718e5bb3abd10a0a099aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4a0582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np101",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb1600603ea31446c716fece48a379fb946eab40182133a8032914e868bb4929e",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x65",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x3f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1d0206",
+ "blockHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4",
+ "validatorIndex": "0x5",
+ "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np102",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd3908889240ecc36175f7ac23e9596230ea200b98ee9c9ca078154288b69c637",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x66",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x3fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1961c6",
+ "blockHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4",
+ "transactions": [
+ "0xf88452831961c7830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0c43b4e8ddaecaadfc1fd4b35659ced2bbaa2ab24b1cff975685cd35f486a723fa056a91d2ff05b4eae02ee1d87442ec57759e66ec13bfd3ea2655cf4f04b6e863d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xefc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np103",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd66957c43447a6edfb6b9bc9c4e985f28c24e6ce3253c68e5937c31c5d376f94",
+ "receiptsRoot": "0xd99d12e61c8e9be69f1eb49cea2f72664c7e569463415b064954bf5e0dbc6a01",
+ "logsBloom": "0x00000000000000000000100000000000200000000000000000200000000000000000000000040000000000200000000000000000000000000200000000000000000018000000000000000000010000000000000000000000000000000000100000000000000000000000000000000000000000000000000000800200000000021000000000002000000000002088400000000000000000000000000000000000000000000000000000000010000000000800000080000000000000000000000008000000000000000020000100001000000000080000002000400000000400000000000000002200000000000000000000000000000000000000000020000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x67",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x406",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16375b",
+ "blockHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d",
+ "transactions": [
+ "0xf87b538316375c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0e59d36f30ed2dfc5eb71433457547f63bf4ad98e0a2181c4373a5e7ddf04d17ea06dce4f88f48f6fd93c2c834537a8baef27bb2965b9e2ce68dc437adb3d657d28"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np104",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe06685d528d0c69051bcf8a6776d6c96c1f1c203da29851979c037be2faac486",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x68",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x410",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1371a8",
+ "blockHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d",
+ "transactions": [
+ "0xf86654831371a98302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a427e65413948a8a1cf63c15214525d05bffca4667149c6a4019513defe57e6ba02819aa7d6a404a7f0194ef3ba7ec45b876f4226b278ebbcfa4012a90a1af3905"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np105",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32d5d07d12d91b8b4392872b740f46492fea678e9f5dc334c21101767bd54833",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x69",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x41a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x11056d",
+ "blockHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e55018311056e82520894de7d1b721a1e0632b7cf04edf5032c8ecffa9f9a0180c080a02a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97a027c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np106",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf89d6d5f7a16d98062e1ef668ee9a1819b0634bd768ece2fc2b687f8968dc373",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x424",
+ "extraData": "0x",
+ "baseFeePerGas": "0xee50e",
+ "blockHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x5",
+ "validatorIndex": "0x5",
+ "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np107",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaf4107a57da519d24d0c0e3ae6a5c81f3958ddc49e3f1c2792154b47d58d79a1",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x42e",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd086d",
+ "blockHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35",
+ "transactions": [
+ "0xf88456830d086e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04c088a3642c3cfad977a0927e6d694bd26be96246f127f03d37fe2b494b99da2a00ef5b6e7aca1ac95ef964978a7ec4bb66688fbb7abace43f90f0c344196379e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np108",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9afc46d870489ac06cac1ea0b65c417d8e0086f0fb828dd92dca30da737c827b",
+ "receiptsRoot": "0x9b9c6d15a59d6b1c222cc63abe6aa28d734463877a3c34d4b3d9e80b768b77aa",
+ "logsBloom": "0x00000000000000000000000000000080000000000002000000000002000000000000004000000000000000000000010000000000000000000000000000000000000400000000000000100000000000000000200000000000000000000200000000000000000008000010000000000000000080000000000200000008000400000000000000000400000000000000000008000000001000000001000000000000000000000000008000000200000000000000000008400000000000000000000000001000000000000000000000001000010000000020000000040000000000000000000000000000000200080000000000000000000000040000000200000400",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x438",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb684d",
+ "blockHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa",
+ "transactions": [
+ "0xf87b57830b684e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06789a9252207970001fd703c22b2b7e5c0388bf018bc070a0469129f80cc5d63a048de0e437b02a8dd3a783892ad1691a1062cd73ddd35c481d9632f5158650317"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np109",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x02324f55d0548cb8743857fe938f91e6f15bfbe94654aadde56c59f83083980a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x442",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9fbe4",
+ "blockHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3",
+ "transactions": [
+ "0xf866588309fbe58302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07e3ef87807ccd797a0020fade1b7d65a7b190fbe40a6f8bdc35cd6a3a6fbed73a0283ad99e27eb389ca3b389bce3c29b3c711b74b6ecd05b290c7be33389830fab"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np110",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9932915761c4c894fc50819df189e875d3b025a7c045406fe415abe61d0e3086",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x44c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8bd6c",
+ "blockHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0",
+ "transactions": [
+ "0xf869598308bd6d825208941b16b1df538ba12dc3f97edbb85caa7050d46c1401808718e5bb3abd109fa0abbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62ca03aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np111",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2849b35fb3ec8146f637be768e3eaefda559928f8bb35753584d5b326a400ff5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x456",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7a5e7",
+ "blockHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x6",
+ "validatorIndex": "0x5",
+ "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np112",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2f24b6182543c677e7d1cab81bc020033c64e034571a20ecd632e252c8f202b3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x70",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x460",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6b12b",
+ "blockHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc",
+ "transactions": [
+ "0xf8845a8306b12c830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf8a8863f63a16d43652b12e54dc61bd71c8ab86d88aebb756c6e420fca56a1aa01f62e0032c57f1629ee82b4fefb8d6c59a85c5c2889b1671ce0713581e773b6e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np113",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d6c9c24ef7d93db6ba57324fb6f3604b09611301e12d250162c2b2b50871625",
+ "receiptsRoot": "0x257c29f688aaf63db2244378182225d104d84cfbd188c82b92323623d11574e9",
+ "logsBloom": "0x00000000000000000000080040000000000000000000000000008000000000000000000000000000000000000001000000000000000000000040000000040010000100000000000000400000000000000000020000000000000000800000000400000000000000000000000040000000000002000100400000000000000200000000000000000000000008000000010000000000000800000000000000000000000080000000000000000000000000000000080400000000000000000000400000000000010000000004000000000000000000000010020000000000000000000000000000000100000000040000000000000000000000200000001800000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x71",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x46a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5db80",
+ "blockHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f",
+ "transactions": [
+ "0xf87b5b8305db8183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0f893fcd21c2a882bc3968ea3c41dd37a8dbfbf07a34a8694a49fdd8081996e25a0502578b516e04b1939fdad45fd0688e636d57f59826a8e252b63f496b919d91c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np114",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x61c50266ae62e14edea48c9238f79f6369fd44e7f3d6519c7139aa1e87ee13ba",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x72",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x474",
+ "extraData": "0x",
+ "baseFeePerGas": "0x52063",
+ "blockHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d",
+ "transactions": [
+ "0xf8665c830520648302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0961de3e3657fdc49c722cc23de35eaf41de51c3aab3ca9a09b3d358fc19195aca060ee48b2fad3f3798111a93038fcb5c9c9791daf3c6acbaf70134fd182b5c663"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np115",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2bebf2f158ec1b8c7be21ef7c47c63fa5a3eb2292f409f365b40fa41bacb351e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x73",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x47e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x47cdc",
+ "blockHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e5d0183047cdd82520894043a718774c572bd8a25adbeb1bfcd5c0256ae110180c001a02ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196a077a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np116",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b359e20c5966cdcbb7b0298480621892d43f8efa58488b3548d84cf2ee514c1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x74",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x488",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3ed55",
+ "blockHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x7",
+ "validatorIndex": "0x5",
+ "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np117",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9776b87f7c94469bd3f80d7d9b639dace4981230bbb7c14df9326aafe66f3da4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x75",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x492",
+ "extraData": "0x",
+ "baseFeePerGas": "0x36fab",
+ "blockHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9",
+ "transactions": [
+ "0xf8845e83036fac830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08315d9fb30662071b05a4e38240e4b85b8e240c0c3e190f27ada50678236c6e7a00ee07dc873780f17ac9d0c7b3d434f89be92231cfca042ca5f23d3f3d7346861"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np118",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcd5cc668a3b28217e9fd05ddaea82d453a6a7394770a888b7d88013a4c9bcb22",
+ "receiptsRoot": "0xe35b2accd70b81901c8d0c931a12687e493a489ed7b82d78ade199815c466d5f",
+ "logsBloom": "0x0000000000000000000000000000000000000a00000000000000000000000000000000000000000000018000000000000000000000000000008000000000000048000000000000004000000000000000000008000000000000000000000020000000000000000002201010000000000000000400000000200000000000000000000000000000000000000000200000000000a200000001000000000000000000000000200000000000000000000400040000000000000000000000800000000000000000001800000000000802000000000000000000000080000000000000000000000000000000000000000000000000400000010800000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x76",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x49c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x301f5",
+ "blockHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305",
+ "transactions": [
+ "0xf87b5f830301f683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a3952a3372b48d4ef804b20a0ff5bbd5440156de3b71d37024356a3c1c5205d8a02ff03cae2dc449ca7ed7d25c91f99b17f0bafcdaf0ecc6e20bdeb80895c83e82"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np119",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdd592cc191ae4ba2be51a47d5056c2f0ba8799c74445ea3f294e0fc95a973f16",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x77",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x4a6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2a1e1",
+ "blockHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0",
+ "transactions": [
+ "0xf866608302a1e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0fd1714b8a15fa8a4e3ffe824632ec26f1daa6ce681e92845d1c1dfe60f032b4ea074bd5a60859bd735bbc70c9531a3ff48421f5c3b87e144406ee37ef78b8fda37"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np120",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4b5122bd4713cd58711f405c4bd9a0e924347ffce532693cce1dd51f36094676",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x78",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x4b0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x24dea",
+ "blockHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd",
+ "transactions": [
+ "0xf8696183024deb825208942d711642b726b04401627ca9fbac32f5c8530fb101808718e5bb3abd109fa0b4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6a0676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np121",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18484e0a8e7bcccf7fbf4f6c7e1eff4b4a8c5b5e0ba7c2f2b27da315a0a06f97",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x79",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x4ba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x20438",
+ "blockHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x8",
+ "validatorIndex": "0x5",
+ "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbe3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np122",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6c921d64a95659dd6c62a919f2df9da2fda7cb8ec519aeb3b50ffb4e635dc561",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x4c4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1c3b1",
+ "blockHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca",
+ "transactions": [
+ "0xf884628301c3b2830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f48d056f98b681d69f84fcde715c63b1669b11563164d7c17e03e5d3a4641a0fa010fce327ee99c5206995065cbb134d5458143a34cbc64b326476aeef47ae482a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np123",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09df4733053f80da4904bce8d847883472e20bc3b1378eb1579e2e3df44d3948",
+ "receiptsRoot": "0x03ecb1b96e21ef88b48a9f1a85a170bdb0406e26918c7b14b9602e6f9a7e6937",
+ "logsBloom": "0x00000004000000000000002000000000000000004000000000000000000000000000400000400000000000000000010000080000000024404000000000000000000000000000000800000000020000000001000100000080000000000000000000000000000800000000000000000000000014000000000000000000000000001000000000000002000000100000000000000000000000000000040000000000000000000000000000040000020000000000000000200000000000000000000000000000000000000000000480010000000000000000000000040000000000000000000000000008000000000000000020000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x4ce",
+ "extraData": "0x",
+ "baseFeePerGas": "0x18b5b",
+ "blockHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90",
+ "transactions": [
+ "0xf87b6383018b5c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b223787310f8ba4f9271d98c8bfc4f7e926ced7773cab6b5c856fb4c43b6dad5a07d0edf043f5b767ffd513479a43cbdc3dcbd18f254e3eb11043d4d7aa4dd7445"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np124",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x15da947afcb1ba68f9fe2328e500881a302de649bd7d37f6e969bf7ec1aca37d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x4d8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x15a06",
+ "blockHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21",
+ "transactions": [
+ "0xf8666483015a078302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa037c41575c8abba9465870babe53a436d036974edf6a9de15d40fff1b4cca7552a07e815124c036ad7c603e7faa56d1d9e517d60cee33c1e47122a303e42d59b6fa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np125",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa085ae940536d1e745cf78acd4001cb88fbc1e939151193c4e792cb659fe1aa0",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x4e2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x12ee9",
+ "blockHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e650183012eea82520894d10b36aa74a59bcf4a88185837f658afaf3646ef0180c080a0882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2aa041356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np126",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfb39354666f43e8f8b88f105333d6f595054b2e1b0019f89bf5dbddf7ec9a0ab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x4ec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x10912",
+ "blockHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x9",
+ "validatorIndex": "0x5",
+ "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np127",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb042b6a0d783d5e3757a9799dbc66d75515d0a511e5157650048a883a48d7c75",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x4f6",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe7f0",
+ "blockHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161",
+ "transactions": [
+ "0xf8836682e7f1830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e5232243797a918b702f03aa9ccf4e944ff52293e7f5b7b1cb6874047f064ed6a02ae2cefc3e4fdb15fb4172d6fe04c7d54a312d077dcd15f91bf5f7047c10d079"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np128",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0400502ad286f8ca3e6e362d38ec9f2119eddc480e9af1ec646bc48e5451a379",
+ "receiptsRoot": "0xdcfb036965921ecaf598a6a02e3fb77784da94be9ed9aeee279d085a20342e47",
+ "logsBloom": "0x00000002000041000000000200000200400000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00080000000000000000000000000000000000000000000400000000000000008000000000000000000000014800000000000000000000000000000000000000000000000000000000000080000000000008000000000000000000000000000008000000000000000000000100000000000000000200000000000000000000000000000000000000030000800000000000000000000001000000002000000000000000020000400005002000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x80",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x500",
+ "extraData": "0x",
+ "baseFeePerGas": "0xcb03",
+ "blockHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2",
+ "transactions": [
+ "0xf87a6782cb0483011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07e94803268c610035c580891ef0c6edd5c21babd8a2bb54d22373e982db9bf46a0375bc266e5e65f0a899b2299ddddbdc0e0d7d40c21e6d254d664abd7d0698076"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np129",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1f1fc8702bf538caf0df25f854999a44a7583b4339011bc24dadcee848e3daf5",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x81",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x50a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb1ae",
+ "blockHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d",
+ "transactions": [
+ "0xf8656882b1af8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a064097d6048ea289fa6b8a002f4a7d53d8381ee46bf0dadd3ac1befa477cef309a0300f780844db5eaa99ff65752886da8b671329d7c12db4e65dd7f525abe9b1d8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np130",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb04a7bb7f21e64f23bd415ee3ad1dc8a191975c86e0f0d43a92a4204a32ac090",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x82",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x514",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9b8b",
+ "blockHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f",
+ "transactions": [
+ "0xf86869829b8c82520894a5ab782c805e8bfbe34cb65742a0471cf5a53a9701808718e5bb3abd10a0a078e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245ea07563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np131",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfd2a1032389a1b7c6221d287a69e56a32d8a618396b8ef829601a9bcb3e91cce",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x83",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x51e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x881d",
+ "blockHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xa",
+ "validatorIndex": "0x5",
+ "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np132",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x91120613028234db2b47071a122f6ff291d837abe46f1f79830276fd23934c56",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x84",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x528",
+ "extraData": "0x",
+ "baseFeePerGas": "0x771a",
+ "blockHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3",
+ "transactions": [
+ "0xf8836a82771b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0a295fe01d21a6f8ffd36f8415e00da318f965a12155808a0d3b51c2c1914cf65a055022813f479686f077e227f3b00dc983081ad361dd8c8240b84d1cf86721ccf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np133",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1ec4000ab57cb0fec41b7221fff5ad7ec0dd4a042a739349045110b8116650c8",
+ "receiptsRoot": "0x870c88b91d896f4d6c0d6d8d9924dee345e36915e9244af9785f4ca1fea5fda3",
+ "logsBloom": "0x000000000008000000004000000000000000000000000000000000000000000400000000080000000000000000000000000000000000000000000000000c0000000000000000000002000000080000000000000000000004000000000000000000000000000000000000000000020000000400000000010000000040000000000000000000000000000004000000800008000100000202000000000000040000000000000000002000000000200000100000000000010000000000000001010000000000000000000000100000100000000401000000000000000000000000000000000000000000000000000000410000000800000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x85",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x532",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6840",
+ "blockHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69",
+ "transactions": [
+ "0xf87a6b82684183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09ce0e0b4fb662dd87cf69350e376568655ce9436941c42e7815a0688db3d8281a037208359ff73e2b9389d9d6e32df5203a0239e5dbbf016e87b3714c122ff081f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np134",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb078e743044057e03f894971bfc3dca4dc78990d5cba60c7c979182c419528cf",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x86",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x53c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5b3e",
+ "blockHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324",
+ "transactions": [
+ "0xf8656c825b3f8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd01a89a43af89dfba5de6077a24873a459ee0c8de3beaa03e444bb712fdbebda04f920e07882701d12f9016e32bfe5859d3c1bf971e844c6fcd336953190a8aad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np135",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5ed1a679a1844883bb7c09f1349702b93a298fc8a77885f18810230f0322d292",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x87",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x546",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4fe0",
+ "blockHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e6d01824fe1825208944bfa260a661d68110a7a0a45264d2d43af9727de0180c001a00bb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8a03b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np136",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd4db74075dc9ae020d6016214314a7602a834c72ec99e34396e1d326aa112a27",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x88",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x550",
+ "extraData": "0x",
+ "baseFeePerGas": "0x45e6",
+ "blockHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xb",
+ "validatorIndex": "0x5",
+ "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np137",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfd5f001adc20a6ab7bcb9cd5ce2ea1de26d9ecc573a7b595d2f6d682cf006610",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x89",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x55a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3d2a",
+ "blockHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c",
+ "transactions": [
+ "0xf8836e823d2b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e853c07d5aba01cfcacc3a4191551d7b47d2e90aba323bd29b5b552147bc4055a03a7e1dee0d461376b43ac4c0dd1a85cc94e9fa64aa8effec98c026293e47240a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np138",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3bf11932c08c5317c7463697409eba5a6904575cc03593cb0eac6c82093d79b7",
+ "receiptsRoot": "0x3ef7cc7ec86f1ace231cdf7c7fadaf27ae84ad4afdd5f2261b60d5be03794001",
+ "logsBloom": "0x00000000000000000000080000000000000000000000000000000000000000000000000010000000004000008000000000000000000000000000000080001000000020000000000000000000000000000000000000000000000010000010200000040220000000000000000000010001000000800000000000400000002000000000000000000000400000000000000800000000000400000000000000080000500000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000004002000000000008000000000002000000400000000000000000000000000002000000000002000000000000002000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x564",
+ "extraData": "0x",
+ "baseFeePerGas": "0x358a",
+ "blockHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da",
+ "transactions": [
+ "0xf87a6f82358b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c28b8f557aaf82e47d9e1425824709427513131908ac636f142990468e40909ea05fe11510da000868cfe1a05bdf689a8c1954c87afeb9ef2defbed3075458a6ad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np139",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe8258bde0dceac7f4b4734c8fa80fe5be662ae7238d9beb9669bc3ae4699efa8",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x56e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2edc",
+ "blockHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e",
+ "transactions": [
+ "0xf86570822edd8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a02206472edd9c816508c6711c004500028a4a6a206caf23b20c6828dd60e1533fa0186dc116a92a8455d1cb92ed4b599c3f7cade6cf59da63b1aef46936c3a507e9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np140",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9ff9a193050e74dfa00105084fa236099def4aa7993691c911db0a3f93422aeb",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x578",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2906",
+ "blockHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84",
+ "transactions": [
+ "0xf86871822907825208949defb0a9e163278be0e05aa01b312ec78cfa372601808718e5bb3abd109fa04adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93a0581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np141",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf63dc083849dc5e722a7ca08620f43fc5cd558669664a485a3933b4dae3b84f4",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x582",
+ "extraData": "0x",
+ "baseFeePerGas": "0x23e6",
+ "blockHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xc",
+ "validatorIndex": "0x5",
+ "address": "0x075198bfe61765d35f990debe90959d438a943ce",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np142",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6222bb96d397776358dd71f14580f5464202313769960ec680c50d9ccc2fa778",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x58c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1f6a",
+ "blockHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d",
+ "transactions": [
+ "0xf88372821f6b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa067091ae37d21fdc5f9eed2877bddb24e52f69e80af27a89608b6fba1c5053f32a04817ab7dc0c3eaac266b08a1683c34fcd43098c6219ea5771d35fa3387b705a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np143",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbe8a51adbc81161927f0b6f3e562cd046f1894145010a1b3d77394780478df3c",
+ "receiptsRoot": "0x8c32e3da3725025cad909cb977e252fd127d54c4f4da3852d18ef3976bfe4610",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000001000000000000004000000000000000000000000000800000000000000000000028000000020008000000008000000000000000000000000010000000000080000100000400100000000000000000000000100000000010000000000000000000000000000004000000000000000000008000000000080008000000000000000000000000000000000000000000080002800000000000120000000000004000000000000000000000004000000400000002000800000020000000080000000000000008000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x596",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1b7f",
+ "blockHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078",
+ "transactions": [
+ "0xf87a73821b8083011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de521643ceaf711d0d3b6cda406ef8fba599658fccc750139851846435eba8afa057f5427948ca8d46609925641f81f72115860c16228821020b8020846a4c3158"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np144",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb7933a921b5acf566cc2b8edb815d81a221222a0ac36dac609927aa75744daaf",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x90",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x5a0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1811",
+ "blockHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6",
+ "transactions": [
+ "0xf865748218128302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0afbda9fa76936bc6be4d26905bc000b4b14cae781a8e3acb69675b6c5be20835a03858ad4e7e694bf0da56994a1e5f855ff845bae344de14109ae46607aa4172ca"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np145",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8a6a6386a956afbc3163f2ccdcaeffeb9b12c10d4bb40f2ef67bcb6df7cf64c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x91",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x5aa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1512",
+ "blockHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e7501821513825208947da59d0dfbe21f43e842e8afb43e12a6445bbac00180c080a06ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81eca0568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np146",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9ee7ad908d7c553d62d14ecd6a1e9eac6ed728f9a0d0dd8aa8db149e6e803262",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x92",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x5b4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1271",
+ "blockHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xd",
+ "validatorIndex": "0x5",
+ "address": "0x956062137518b270d730d4753000896de17c100a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np147",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x14111c2a0f5c36f6b8ea455b9b897ab921a0f530aaee00447af56ffc35940e32",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x93",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x5be",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1023",
+ "blockHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea",
+ "transactions": [
+ "0xf88376821024830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa08e5e1207971ec2479337fa7c80f843dd80d51224eb9f9d8c37b1758d3d5acae4a04d2f89fb9005dc18fa4c72e8b1b4e611f90ca9c5e346b6201dfe4b83ec39c519"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np148",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc43ae2200cea3bdd1b211157150bd773118c818669e2650659ef3807ac7d2c29",
+ "receiptsRoot": "0x1f4bdefd1b3ded1be79051fe46e6e09f4543d4c983fdc21dee02b1e43fb34959",
+ "logsBloom": "0x00000000000000000000000000000110000000000002000000000000000000020008000000000000000800001000000000000000000000000020000010000400000000000000000000001000000000000000000000000000000020000000000000101000000000800000000000000000080000000000000000000000000000010000080000080000800000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000200000020000000000000000000000000002000001000000000040002000000024000000000280000000000000000000000000020000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x94",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x5c8",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe20",
+ "blockHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2",
+ "transactions": [
+ "0xf87a77820e2183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b5b7b281fbe78ca0f9819a9015997a42ee896462db5ea7de089cd7e2cf84b346a02bc85175e51da947f89f947c30d7c1d77daa6e654a0007e56de98812039a76bd"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np149",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x21cafe51bfa7793c9a02f20282b59cbb5156dce1e252ab61f98fdd5cdecf8495",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x95",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x5d2",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc5d",
+ "blockHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031",
+ "transactions": [
+ "0xf86578820c5e8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0371194d9f0d8b28bc888d45cc571dd73c9dd620d54184b9776256d5e07049350a05f7bfb7cdccb54a2f0ea01374f1474e694daa1b128076bdc33efcee9bc0d56a7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np150",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x503c44cab4d6c0010c3493e219249f1e30cfff1979b9da7268fd1121af73d872",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x96",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x5dc",
+ "extraData": "0x",
+ "baseFeePerGas": "0xad3",
+ "blockHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746",
+ "transactions": [
+ "0xf86879820ad48252089484873854dba02cf6a765a6277a311301b2656a7f01808718e5bb3abd10a0a0ab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1fa05affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np151",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2e257bca2ea424f7c304c42fc35b14c8d3fd46c9066c7f895f775a2065a14bab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x97",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x5e6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x979",
+ "blockHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xe",
+ "validatorIndex": "0x5",
+ "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np152",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa124fe0abd3682da7263262172c9d2c57fb42d4f131cbc9f24ddea0ec1505e48",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x98",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x5f0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x84a",
+ "blockHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7",
+ "transactions": [
+ "0xf8837a82084b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0be58da9e68f28cf1dd209a610214982ba767249f3b92cd8c0fb3850a9ee194d6a0613f59eec6c092b6d2fc55de85bc67b21c261dc48f1ddb74af3aac438b27ccd5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np153",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3c05bdceef0bdc9f676a3a0c00151f975e469e5bb08ab08f3eed090987119672",
+ "receiptsRoot": "0x73faa109b88bfbf7e2a71c36d556d9286c0a26988680cbe3058f045fd361b3b0",
+ "logsBloom": "0x00004000000800000000000000000000000000000000000000000000000000000004000000080000000000000800000000000000500000000000000000000200000000001000000800000000000002008000080000000000000000000000000000000000000000000008000200000000000000000000000000000001000000000000000000101000004000000000000000000000000000000000000000000000000000000080000000000000000000008200000000000080000000000000000000000000000000000800000000000000000000000400000080020002000000001040000000000000000000000000004000000000000000008000008000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x99",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x5fa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x742",
+ "blockHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718",
+ "transactions": [
+ "0xf87a7b82074383011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b9eb0510fdc334dde88b8ac75869aa2dd53988191ae1df94b7b926eae9b18050a00cbd9e12b7185723ed407175a7a70fa5cc0dbc4014b3040a9ade24a4eb97c8c1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np154",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc2e93862e26d4df238b2b83a3ee0e008f25123aa211d83906fcd77bc9fd226ab",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x604",
+ "extraData": "0x",
+ "baseFeePerGas": "0x65b",
+ "blockHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea",
+ "transactions": [
+ "0xf8657c82065c8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e5959821e9fe4b896ef2559fe6524aadead228d89f923061b6d2d340f6b9307fa02ed2929f37d24a57229f7a579aaab2d9551e71b0822895e91f04e7824da9a861"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np155",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0c94e7ea002f7b3bcc5100783e1e792160fb73ff4e836cd295e34423ff72f2a6",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x60e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x591",
+ "blockHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e7d01820592825208948d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f20180c001a0f9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897a04cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np156",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x04ba5addea7916f0483658ea884c052ea6d759eeda62b9b47ee307bd46525bb0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x618",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4df",
+ "blockHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xf",
+ "validatorIndex": "0x5",
+ "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np157",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ae465791b7ce8492961c071fc50b34434552a1ab36c1854fbc308f55729e827",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x622",
+ "extraData": "0x",
+ "baseFeePerGas": "0x444",
+ "blockHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a",
+ "transactions": [
+ "0xf8837e820445830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0140e450a0bc12c61bdf6acca1a56178466d88014d00a4a09c1088ce184128327a07daad374bb0d7fe879212bd7bdc8d454b4996bd7bebd6f6d0d4636ec7df28d0b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np158",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe01f0f54fba649cdc0d6da6a9f519b6918149d82f134845e99847ff7b362b050",
+ "receiptsRoot": "0x36340e11a5f180862d423a676049d1c934b8d27940fdd50dc8704563ffd27b0f",
+ "logsBloom": "0x00000000000000008000000000800080000000000000000018040000000100100000000000010000000000000000000000000000000000000000000000010000000080080000800000000000010000000010000000000802000000000000000000000000001000000000004000000000000000000000004000000000000000004000000000000000000000000000000000000000000000401000000000010000000000000000000000000000000080000000000000000000000040000240000000000000000000000001000000000000000000000000100000000080000040000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x62c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3bc",
+ "blockHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0",
+ "transactions": [
+ "0xf87a7f8203bd83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0331dd2ec5bf4bddde96cacb8a28ed1cc577d4a2289bae6da0e6ef3c9b1287fc3a04c2925895dfbed2b00ac9a2040371970da1a7fd333dc1e551e2e268c56717c79"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x00ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np159",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa6e1d00e54b539beb170e510a8594fdd73ad2bf8e695a0f052291454ee1f3ade",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x636",
+ "extraData": "0x",
+ "baseFeePerGas": "0x345",
+ "blockHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004",
+ "transactions": [
+ "0xf86681808203468302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0f4a1b0681bb3c513fa757b560ef9cf0f004b8da91d920e157506ebb60d0d3954a0738da3b003ce68a9b4032770c0fe6481f54ea43baba54cad7153369486728790"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np160",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9277b9454326e993436cef0b9a2e775cff46439f3d683da55a983e9850943a20",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x640",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2dd",
+ "blockHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0",
+ "transactions": [
+ "0xf86981818202de82520894c19a797fa1fd590cd2e5b42d1cf5f246e29b916801808718e5bb3abd109fa0857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291a07d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np161",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc9f74f81ace1e39dd67d9903221e22f1558da032968a4aaff354eaa92289f5c6",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x64a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x282",
+ "blockHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x10",
+ "validatorIndex": "0x5",
+ "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np162",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x853c0a8e4e964cc857f2dd40b10de2cefb2294a7da4d83d7b1da2f9581ee0961",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x654",
+ "extraData": "0x",
+ "baseFeePerGas": "0x232",
+ "blockHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d",
+ "transactions": [
+ "0xf8848182820233830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01a7b8af754eba43e369957a413a3fef1255659f2bd05f902b29ee213c3989d46a00ca88ac892d58fdb0d9bd7640ca797280081275886cc2ac155a814eb498e7d7b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np163",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd89e02bde63bf214ad6a3bc94f3b092bc2a1fbc13f172049c854ecb070630fe6",
+ "receiptsRoot": "0x596413315e1e3fd6fc21e4ce81e618b76ad2bf7babfa040c822a5bcbffeb63be",
+ "logsBloom": "0x00080000001044010000000800000000000000000010000000040000000020000000800000000040000000000000000001008000000000800000000000000000000000001000000000020000080000000000000000000000000000000000000002000044000000000000000000000000000000000000000000000000000000000000002000000000000000800000000000000000000000000000000000104000800000000000000004000004000002000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000800020000000000000000000040000000000000000020",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x65e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1ec",
+ "blockHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa",
+ "transactions": [
+ "0xf87b81838201ed83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06e6e8187c035f2788ba44e3f47b4102a1f263ae2f601b2fbfa9e2cdc3b0c22b1a06c229eebca1bdda1aba424cd8cf296f386cf2d50a6add950fd6cb34aac442c5a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np164",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe2672f9ae97aeaeb22f42c389301a3b79ad6c47ad88c54e18e1d7a4ed5e9c903",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x668",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1af",
+ "blockHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13",
+ "transactions": [
+ "0xf86681848201b08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08ab61fe0265afe289954f7c2af8e070f3c40dda39e6cb6ff5c798fc7bc87b55ba00a8a440a7ba5a04a7bb73b093e94734dda228d33a43c640d719aef5ea5e81764"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np165",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4d9cd7b52c0daaec9a019730c237a2c3424f5d5a004c8bc9fa23997f3ec33768",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x672",
+ "extraData": "0x",
+ "baseFeePerGas": "0x17a",
+ "blockHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e81850182017b825208946922e93e3827642ce4b883c756b31abf800366490180c080a089e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299a03d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np166",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x03629dac3f669a8262e8246d46bac9acfb7cbca336d02e90c081561fa0b22aba",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x67c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x14b",
+ "blockHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x11",
+ "validatorIndex": "0x5",
+ "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np167",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4f5e79d4af5565b3b53649b1ddc3a03209cb583e7beb03db8b32924c641e6912",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x686",
+ "extraData": "0x",
+ "baseFeePerGas": "0x122",
+ "blockHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9",
+ "transactions": [
+ "0xf8848186820123830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b2aafb3e2678dd48e6f31874bd478778480815c9d110ec8cc77a42f7d52999daa00705b1266fc1087167cc531caa9d2e0a0c8779e4ad5020d9d3a16500bf5b96a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np168",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c6c100b7c75ced82b38315fd50c5439478a7ee256073ce17b845e0815912eab",
+ "receiptsRoot": "0xf8f8c85b17ada66c06f8e41b58b45213619bb309a197896adbaff4e9139967b1",
+ "logsBloom": "0x80000000000000000000000000000000800000000004008000200000000000000002820000000000000000000000000000000000000040020400000000000000000000000200000000000000000000000000000040000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000040080000000000000000000000000000000000200000000000000080000200000000000000000000000000000000000000000000000000000100000003000200000000000000000000000000000000000000200000000000000000000000004000000004000000040001010000000080400000000000000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x690",
+ "extraData": "0x",
+ "baseFeePerGas": "0xfe",
+ "blockHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1",
+ "transactions": [
+ "0xf87a818781ff83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b1e7ca73ef581fc880deb34aa6cf7958f6ce110efd121d48fb2292a747864815a02bf94b17dc034d8934b885faa269a9430a755ebfb4c6e87378376a094704f464"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np169",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9f527744fd44cf4c2ba60fe62d25d4f19e64c034cbf24785e0128d5fafa19e2a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x69a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xdf",
+ "blockHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d",
+ "transactions": [
+ "0xf865818881e08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c583bd1010c1e4158466575fb0c09ff710a5ff07c8f7a6e7960d90bffef8bd34a059ea0ba5c6fc64aad73252c780de287599d3100d80f7b1d3201b4865d82c0cad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np170",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x45c5f07a7d94c320222f43c12b04081fdbe870be18a2b76f7122bd7f4554118b",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xaa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x6a4",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc4",
+ "blockHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c",
+ "transactions": [
+ "0xf868818981c582520894bceef655b5a034911f1c3718ce056531b45ef03b01808718e5bb3abd109fa0626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9fa07271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np171",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf4a19b9765604687783462dbf36a0063ada2ba7babb4dd1c4857b2449565a41d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xab",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x6ae",
+ "extraData": "0x",
+ "baseFeePerGas": "0xac",
+ "blockHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x12",
+ "validatorIndex": "0x5",
+ "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np172",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4f9e280291036fb6cd64598fe0517d64d6da264d07d7fc3b8d664221d7af9021",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xac",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x6b8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x97",
+ "blockHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5",
+ "transactions": [
+ "0xf883818a8198830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a05f47b0ab77130dcc8f7143a2afaace6a2d1f82e25839cb9adee5aaebfe7dc681a05af90b75de35c90709b83861d8fdfd7805a89b1e76a4bdd5987e578ba72fc37e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np173",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe01cadedc509806ea9cd7475312a3768de034d1c849abadc46237b8cd4163179",
+ "receiptsRoot": "0x15dc68f6de1b068b96d32dbc11a048b915e7d62bd3662689ae5c095bb6ddab37",
+ "logsBloom": "0x00000100000000004000000004000000000000000000000000000000000000000000000004000000018004000000000000000000000000000002000000000000000020002000400000002000020000000100000000000000000080010000400000000000000200000000040000000000000000000000010000002000000000000000000000000004040000000000000000000000000000000000000000004000000000000000000000080000004000000000000000000000001000000000000100000800040000000000000000000000000000000000000000000000000000000000000000400000000000004001000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xad",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x6c2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x85",
+ "blockHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb",
+ "transactions": [
+ "0xf87a818b818683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04a74ea0833e42d624ba0d9b589a16e05feae1c2dee89abfb29df95b650d3e756a037135f3e24572eb9d927a02c0c4eee7fd5d8a181e2384ef3b3b04c49c9dbbbe1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np174",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa862687747ffc388414ee5953589a70f2161a130886348157257a52347be9157",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xae",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x6cc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x75",
+ "blockHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4",
+ "transactions": [
+ "0xf864818c768302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a024414367540c94b1bd3ce29dd0b4ee6bdece373f9417e96f0ef8d632e82c4ecba031dae9539e84f7351a5b92f1246dfd909dd5a383011fbd44bb8e87fb6870189b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np175",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd70339e1158ecc97dc7db86b3177202ffa3dcba386fd52e54e6fe8b728003154",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xaf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x6d6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x67",
+ "blockHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e818d0168825208945a6e7a4754af8e7f47fc9493040d853e7b01e39d0180c001a08c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122a028e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np176",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1bc27508b52de3a750cc928dd89954462b4e4dbfb60707442e60b4b23aabb816",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x6e0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5b",
+ "blockHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x13",
+ "validatorIndex": "0x5",
+ "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np177",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x78497ebf1fbf03732772a8c96b2fe6902af5ab844e49f2685763b4366ce8ddf6",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x6ea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x50",
+ "blockHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238",
+ "transactions": [
+ "0xf882818e51830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fd5ea8b7df5c3ecd87220b8ad7d15198722d94a64b0e8e099c8c7384c1d08a33a039707925aba6dad8d06c162fd292df0bf03033b7b6d1204ae4be0ce6f487fa71"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np178",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x197c4166e7f8f68ee6965c87c8ce720bee776a7b7119870371e6262bc913468d",
+ "receiptsRoot": "0x7c66f99e4434aa19cdf8845c495068fa5be336b71978d6fa90966129f300218a",
+ "logsBloom": "0x00000000000000000000000000400200000000000000800000000000000000008000008000000000000000000000000000000000000000000040000004000041004000000000000000000000000800000000000000000000000000000000080100000000000000000000000020000000004200000000001000000002000000100008080200000004000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000800000000200000000000000000000100002000000000000000000002000000000000000000100000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x6f4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x47",
+ "blockHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf",
+ "transactions": [
+ "0xf879818f4883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03e0f9aa0ca6ec8b4f9e7fccd9b710c0de4414618726e298b36816cd6d689a89aa07d3950b5ebbaa58f5c4e0bc0571499d9d58d563ce2c039664cf210815e43d0e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np179",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf56610f73e08c2ccaaa314c23bc79022214919c02d450cab12975da3546b68fd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x6fe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3f",
+ "blockHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468",
+ "transactions": [
+ "0xf8648190408302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f41a67e92f032c43cc601daa205026cc5a97affb0f92064991122a1aa92428dfa0237053c462847907c840ada5076caab16adc071da181e9277926a310adcb8e3d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np180",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfa57370da0cc72170d7838b8f8198b0ebd949e629ca3a09795b9c344dead4af5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x708",
+ "extraData": "0x",
+ "baseFeePerGas": "0x38",
+ "blockHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517",
+ "transactions": [
+ "0xf8678191398252089427952171c7fcdf0ddc765ab4f4e1c537cb29e5e501808718e5bb3abd109fa076a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7a01a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np181",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d3f029e56f9ee3db9ed8f9156cd853fb1fcafe05475ec8c2a4dd337a5e3e20e",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x712",
+ "extraData": "0x",
+ "baseFeePerGas": "0x32",
+ "blockHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x14",
+ "validatorIndex": "0x5",
+ "address": "0x892f60b39450a0e770f00a836761c8e964fd7467",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np182",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58a6332c9e7b85155106515f20355c54bb03c6682024baa694cbaff31c3b84ff",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x71c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2c",
+ "blockHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c",
+ "transactions": [
+ "0xf88281922d830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01ae40537174a716b5f33d153e9251ae8c1d72852da25823f6d954b9dbc5740cca02ff07812990e0645cab5c9d89028f7255f50d0eee5bee334b3ba10d71485c421"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np183",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55d4e87d040358926c84414b854fc47a75b9963df75e359a2182464c51201088",
+ "receiptsRoot": "0x1fccfe93768ce1ed60d0f83cbc8bef650cb1d056c35a4b233ae41a1b8219f92d",
+ "logsBloom": "0x00000080000000000000000000000000000000000000004000000000000010000000000000000000000000000000014000800000000000000100102000000000000000000000020000000000200000000000000000100000000000200000002000000000000000000000002000000000000000000000000000000000000000001000002000400020040000000000000200000000000000000000000000000000000000002000000000000000000000100000000000022000000000000000000000000000000004000000080000000000000000000000000004004000000000040002000040000000000000000000000000000000000000000000000000100000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x726",
+ "extraData": "0x",
+ "baseFeePerGas": "0x27",
+ "blockHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4",
+ "transactions": [
+ "0xf87981932883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa02d1dcc844efba97a51917ab3d79f837680f42e2e76ab51b4b630cbe9a6e4e10ea03d3f624c82de14b23b0c5553621cc9a4c649cd856a616f5a91bad8bf0c0d1709"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np184",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd3ec16ab633987e17a4e8c573014b1fc9919f004b3cb80da11280d1caad1fe3e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x730",
+ "extraData": "0x",
+ "baseFeePerGas": "0x23",
+ "blockHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94",
+ "transactions": [
+ "0xf8648194248302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a01e5301a3386e11893c0275367ac5d31fea88f31731e66ee769bfddc3486cff1aa0203dbf8bbfa9df2d635e1889d51e06611e8c2a769609908aeb5e97decb03b141"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np185",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x692ddd6938f00a07474233619f579b30c1eaaef353a2b0cc24b47d7898aa5c49",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x73a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1f",
+ "blockHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e819501208252089404d6c0c946716aac894fc1653383543a91faab600180c080a0039c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8aa05ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np186",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9eac86abf4371646a564bb6df622644682e5de5bf01fed388ccaf10700e46e88",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xba",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x744",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1c",
+ "blockHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x15",
+ "validatorIndex": "0x5",
+ "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np187",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xff13e99ee95ffe82139758f33a816389654a5c73169b82983de9cf2f1f3dbd9f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x74e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x19",
+ "blockHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a",
+ "transactions": [
+ "0xf88281961a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0276782d84f5f6ab0805be5e57923747bae9fa2b06ed4b45bcc364bdb4f09eca1a0484f9fc2a31a4b5f24ba33da54649e6a3261c0bee52d91576246bb54698c1535"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np188",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x522c1eb0c4d1332668a2e3676efd54899579d85fd4e7007fd228702d9c964baa",
+ "receiptsRoot": "0x90d4e326daf1e15e41687f281f8e638992c4cdfbe590eb4956fd943aa39f1bba",
+ "logsBloom": "0x48000040000000000000000000004000000000000000000000400000000000002000000000000000000000000000000018000000000000000000002000000000000000000000100000002000000800000000000000000000000000002000000000000000000000000000000000000000040000020000040000000000000000000000000101000000000000000000010000000000040000000000000000000000008000000000000000000000800000000000201008000000000000001000000000000010000000000000100000000000000000000000040100000000000000000008000000000000000000000000000000000000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x758",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16",
+ "blockHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d",
+ "transactions": [
+ "0xf87981971783011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0870548904b9e901c294fd1c04a6cff92fbb40491e00a1ffcbc551c6c5eba2db3a0524ff53000a94b71aef3a2c516354bc5d7fdb3f236d4647020762a56d9bd2fbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np189",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfb0eecb29a002997c00e0f67a77d21dd4fa07f2db85e3e362af4bbfcb69b6c12",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x762",
+ "extraData": "0x",
+ "baseFeePerGas": "0x14",
+ "blockHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1",
+ "transactions": [
+ "0xf8648198158302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0111d3d32f82c89fc830943a4aa0b20e013886491e06acede59ea4252b3366c05a07b9f9199ecdb210151db8a50c74fa1488b198db4e5dda3ad1fa003b70d9bd03a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np190",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x36fce9409ec76cfda58bd4145be0289d761c81131ed0102347b96127fd0888e2",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbe",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x76c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x12",
+ "blockHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9",
+ "transactions": [
+ "0xf86781991382520894478508483cbb05defd7dcdac355dadf06282a6f201808718e5bb3abd109fa0910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178a02ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np191",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd5d1fc871c3a4694da0e9a9f453c0e6f4c8f38fbef45db36c67cd354e22eb303",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x776",
+ "extraData": "0x",
+ "baseFeePerGas": "0x10",
+ "blockHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x16",
+ "validatorIndex": "0x5",
+ "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np192",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4d19a2ce0d61642b6420c9f23ea32bb72ebe24384ed110394d7e5ca98589f055",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x780",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe",
+ "blockHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45",
+ "transactions": [
+ "0xf882819a0f830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02356373d8d8ca7c15e547e717f7327ab0d803867cfabedf8d75e4d1cb264862ca011a3879ae15ab356e9558926382b7fa68b5c5a5c5b127b6f5176523dfe0ae986"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np193",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd67263b379522c5059bb0a7164b9cd3fa70697e4012b3b5c519ecf888dbc5700",
+ "receiptsRoot": "0xc1c820ad9bde8ce9524a7fa712d4849dc2f9f9553e8c00f1fe6c41323e31fbf7",
+ "logsBloom": "0x00000000000000000000000000000000000000000080000000000200000040000000000000000000000000000000000000000000000000000000001000000000000000000000000000001002000004020000000000000000000011000000000000000080000082000082080000000404000000080010000000000000000000000000100000010000000000000400000000000000000000000000000000400402000000000000000000000000000000000000000000200000000000002000000004000000400000002000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000800000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x78a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd",
+ "blockHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3",
+ "transactions": [
+ "0xf879819b0e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03423551e59962468cb263c416cb4025c462624b8c8c687177571976c345a8d20a0190d3ab5979e300998fc96429a75c50e1c195115cada83e01fb14a28f2e294de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np194",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2111d275b4901e864fcded894a9d9a046f9077d8f6c5af65a72c2243a32dbeaa",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x794",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc",
+ "blockHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f",
+ "transactions": [
+ "0xf864819c0d8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b4dac384ec258b1a752856b3fcda42244c3e648577bf52d74f25313b3327bf1ca02f7b54b9475768335aab1778fd7ec882f3adbc9e78d4d04a0b78e93e4d41a76b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np195",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2efd726637cb91156021ac4ae337a87f9a1f28efd620de55b77faef0d3b84b22",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x79e",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb",
+ "blockHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e819d010c82520894ae3f4619b0413d70d3004b9131c3752153074e450180c001a07cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54a03bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np196",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xeba72457992e05a38b43a77a78ba648857cec13beb5412b632f6623521fe248d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x7a8",
+ "extraData": "0x",
+ "baseFeePerGas": "0xa",
+ "blockHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x17",
+ "validatorIndex": "0x5",
+ "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np197",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8713a1c42af83625ae9515312298d02425330b20a14b7040ec38f0655cb65317",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x7b2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9",
+ "blockHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14",
+ "transactions": [
+ "0xf882819e0a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02ed567eed3a763f56fe05c1e44575993df5b6cf67e093e0e9b5ec069ecaf76a2a04891e566e0d136b24d62ffe17f2bfaa0736a68f97b91e298b31897c790b2ed28"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np198",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2250f011d079600d76d5905dca93324f2fceb110390e8a7e7177569bd8ec73fd",
+ "receiptsRoot": "0x8027ec2e573bf62c00695cb9a0f67e28e4cce8dc44dc641d7388e4864d8ff78a",
+ "logsBloom": "0x00080000100000000000100000000840000000000000000000000000000000000000000000000000000000000000000000000000080080000080000000000000000000004000000000000000000000000000000000000000000000000000000200000000000000100100000000008001000000000000000000800000000000020010000000000000000000000000001000800000200000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000012000000000000000000040800000040004000000040000800001000000000000000000000000000000010000100000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x7bc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22",
+ "transactions": [
+ "0xf879819f0983011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c362dc6d498fcbd0eab0518a012a348d87fe4f2e53f7843f350662c43258609ba026d83d49fd9654704da7435b3400713ed7909a7203d6c55b8d43dd1e9fe67226"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np199",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8faa1ccb44b8d8d3ad926bdcb75a9e9fd18fa77728ef12aa9c4ba7be1906d3f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x7c6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad",
+ "transactions": [
+ "0xf86481a0098302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a08683c22fc25a5413b758a32c5a6515b1b055541ad523ae4159c4d04c3f864260a06c8f2e1e929e9df95158a161e793ae162e1e4297f8042bf9358dcc119f5545e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np200",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe4f7f192080fd853f053608561854cdb68eb8de9eda499fd7ad840ca729487d3",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x7d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae",
+ "transactions": [
+ "0xf86781a109825208947c5bd2d144fdde498406edcb9fe60ce65b0dfa5f01808718e5bb3abd109fa015f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391a03b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np201",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5188152524460d35f0c837dab28ac48f6aac93a75ecbb0bcb4af6a9c95e18a67",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x7da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x18",
+ "validatorIndex": "0x5",
+ "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np202",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09f47830b792bc39aa6b0c12b7024fa34d561ff9e0d32c27eab5127239799bb0",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xca",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x7e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8",
+ "transactions": [
+ "0xf88281a208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03b50dfd68a93199762b4b47c08ca4c9f67d99e772f3fec9843a4e1c3ae4d6963a070a7b2cc31e53de9d1fa14f55f28b212979bd83bbd9e9097e65845e05a9ee40f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np203",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a0d6e0a749247b4271d54ddfd2732ceb5b377c1db1ac40aa1d2339d3a143aaa",
+ "receiptsRoot": "0x189141497b4062bfbe61a7fb2f96cc8a95543e38c077c9150b740f8d01a313a8",
+ "logsBloom": "0x00000000000000000000040040000000000000000000080000000000004000000000000000004000000000008000000000000000000080000002008001000000000000000010000000000080000000000000000000200000002000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000020000000000000000000000800040000000000000000400000000000000000400001000000004000001000000000020000000000010000000000000000000000000000000000000000008000000000010000100000000000000001000000010000000000000800000000000000202000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x7ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7",
+ "transactions": [
+ "0xf87881a30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109f9f3c7a9aedd154caa41f602593b4bc78db1101336a81095174d4487dd8338878a0458e45144a4d1a634950ae79ac251065204776baa96a3f94c6d71a00323fe9b4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np204",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda96365c5a33f358ed732463139254c4f186e899ad00b05d9a30ff39d4d1a27d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x7f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1",
+ "transactions": [
+ "0xf86481a4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a82c39f1be580d16334c133165d5ceb8d9942b184ecccea09e73ff45120ac523a04432d6958bb18882f9f07e851abe454039a5b38d61fd975c7da486a834107204"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np205",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2258c0e37e5bedab21f7ea2f65190d1d51f781743653168d02181c8f16246c71",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x802",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81a50108825208949a7b7b3a5d50781b4f4768cd7ce223168f6b449b0180c080a04f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25a0312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np206",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda2ecb481078839fd39c044b3fceae6468338266d9572da0f2281e58b9596914",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xce",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x80c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x19",
+ "validatorIndex": "0x5",
+ "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np207",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf0f20309e2cec2fb6af448c58c40e206b788241bb88e62a8e7479aadc6bfa94e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x816",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da",
+ "transactions": [
+ "0xf88281a608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa079aa26a33abe2e9504cfc6552c6b39434478b081f5cbbb613269d64980edaf93a079ffe44aec63b05644681b948ea0e5a996e106f3e074a90991c963ff3e7a8aa6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np208",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x177fc88f477d3dd466f7cac43b50d4b2b77fd468ef479177ed562d2401acd6c0",
+ "receiptsRoot": "0xd1458a51a7ca8d2c87390d85d986956f392bdd634ffbe4d5a7e2b09a142ce514",
+ "logsBloom": "0x00200000000000000000000000000000000000000400000000400000000000000000100400000000000000000010108000000000000000000000200800000000000004000000000000000002000000000000000000000000000000020002000408000021000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000002000000000000000000000400000000000000000000020000000000000000000000800000000000080000000000000000000000800000810002000000000400000000000000000000000000000000000000000000020000000000000000000000010080000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x820",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a",
+ "transactions": [
+ "0xf87981a70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0969f6d3d90ca6b62cbda31ed28b7522b297d847e9aa41e0eae0b9f70c9de1e01a0274e038abf0b9f2fba70485f52e4566901af94c9645b22a46b19aebb53b4c25d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np209",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55980d8ac0e8bfd779b40795a6d125a712db70daa937ace1f22a5fcd5fd2dfa6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x82a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd",
+ "transactions": [
+ "0xf86481a8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa04973c2a9d2fcff13428e8a3b3f0979185222cad34366777db8dfc6438cdac357a0128ad521391c000e18211ad8ffa45b41962fca43be83a50ce299d3bd4407f44b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np210",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x522d0f5f8de1ef5b02ad61a3bff28c2bd0ce74abca03116e21f8af6e564d7fd2",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x834",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c",
+ "transactions": [
+ "0xf86781a9088252089485f97e04d754c81dac21f0ce857adc81170d08c601808718e5bb3abd109fa0547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0a028cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np211",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda7dd7f5babcf1b3c407e141b4ea76932922489f13265a468fb6ab88891ff588",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x83e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1a",
+ "validatorIndex": "0x5",
+ "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np212",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb6724f1d73bee909624707836e66ffbb21b568dd5bd697668ce18a4ae31818a4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x848",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c",
+ "transactions": [
+ "0xf88281aa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e582e9d64ed6f95da074eaeb70ca1e47e8627bb7cd4e34d5aab01ff49ee6dd90a022cc32cc7c3030b0b47f1f69911311acd2ae3e95f19f766b69ebb67804676262"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np213",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a1c08c9dfcc48c37e349407f37f9c10d9d4c4b1d6c28d30af2630679c74ea96",
+ "receiptsRoot": "0x730ab6f592da8dfc7815bcba110f6de8dd0343aa932f55b589ff99d83b9ec358",
+ "logsBloom": "0x00000000000000000000000000000000000000200000000400000000000000002008008000100100000800000000000020000000000000000000000000000000800001000000002000000000000000800000010000000000000000420008000004000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000004000000000000008000000000000000000000000000000000000000000000000000000400010000000000004000000000000008000000840000000000000000040000000000000000000000000000120000001000000100000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x852",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5",
+ "transactions": [
+ "0xf87981ab0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08747d48d3358eb47195c17f67f22af5eca1177fba591b82b8b626058a347b2e5a0420e02657efee51f73f95017b354b1bca2850269a5de7b307a280c63830f3333"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np214",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x67ca707e9bd81330c2fb9060e88ce0b0905c85c9be26ae4779874f3892ebab0c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x85c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d",
+ "transactions": [
+ "0xf86481ac088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a03752a40997c9b7b9c5dfd48f88990ddc727517540c403dadcb7476b8a4a9d4f6a0780178975646114017be4b06fae0689a979a45166f810604f76934239b0a2b9e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np215",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b5ca86f1650f79fb42d74e523dc4e631989a3175023ced9a239e9bcc2c15a8e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x866",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a",
+ "transactions": [
+ "0x02f869870c72dd9d5e883e81ad010882520894414a21e525a759e3ffeb22556be6348a92d5a13e0180c001a0047b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab669fb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np216",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc1ab95016db7b79d93ee0303af69ce00bdb090d39e20a739d280beb3e301c9d5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x870",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1b",
+ "validatorIndex": "0x5",
+ "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np217",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf8c17319b995ce543f9ace79aab7f7c928b36facae4e6e0dd50991f95bed1542",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x87a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678",
+ "transactions": [
+ "0xf88281ae08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05a8e9e2a3556016a65d5b99849bd44cd6ab17cfb15d7850356c9b491357f0611a01f7d3c43fe1759b4ec768275e918e12dae75db56a5d2140d1403ef3df41f56df"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np218",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05bd7288ee80780a92b234fec2f8bb5bb4d0425721ddbf89d866c62b288f6bff",
+ "receiptsRoot": "0xbebbd614564d81a64e904001523ad2e17a94b946d6dfc779928ec9048cf9a3f7",
+ "logsBloom": "0x40000000000020000000000040000000000000000000001000000000000000021000000000004008000000000002000001000100000000000000002000000000000400000000000008002000000000000000100000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000100000400000000000000000000000000000000000000000000000000000020000000000010040000002000000000000000000000000000000000000000000000000020000000000200000000000200000000000000011000000000201400000000000001000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xda",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x884",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46",
+ "transactions": [
+ "0xf87981af0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b3a49ddc2fc9f12cb1dc0a67623d5a1a6a1b5bf59a8f1736c9f0ab3b564250d3a05fc1ca6dab6b9337827afb55342af8a51fae064157e9c78b76dacd66bbea55d1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np219",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8236fb6bc66022c43d12c08612fd031d8b42852bef9a2dec04c1bc4b83cba489",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x88e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6",
+ "transactions": [
+ "0xf86481b0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08a2bbd86fd1bb42e548fa4b4c4710f6c6ed03b4700f9e3a213bc70d17f016a3ca076d8bf736d722af615228680c31acd9815b9380a8bc5895cddb2361170274a7f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np220",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1d9d412ef451097aa53e4fc8f67393acfd520382a1c4cfa6c99e2fb180a661db",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x898",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6",
+ "transactions": [
+ "0xf86781b10882520894fb95aa98d6e6c5827a57ec17b978d647fcc01d9801808718e5bb3abd10a0a0c71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0a03bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np221",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x830dfc2fb9acb72d3c03a6181b026becbcdca1abf4ab584b2dd00c48fd2f6a62",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x8a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1c",
+ "validatorIndex": "0x5",
+ "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np222",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7492f26a06f6b66d802f0ac93de1640ec7001652e4f9498afa5d279c1c405ccd",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xde",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x8ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794",
+ "transactions": [
+ "0xf88281b208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa09765f880d3815c484a796d3fd4c1791ab32f501ba8167bfd55cde417b868e459a0310fdd4d8d953cf38b27fa32ad6e8922ef0d5bd7ba3e61539dd18942669187f1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np223",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e515c524c17bcb3f8a1e8bd65c8403ae534c5c2c2fc0bddce2e69942c57028a",
+ "receiptsRoot": "0x336f567c728ef05cbd3f71c4a9e9195b8e9cd61f8f040fdd6583daf0580a0551",
+ "logsBloom": "0x00000000000000000000000000000000000000000000400000000000002000080000080000000000000000000000000000000000000000000000000000000000008000000040000030040000000000800000000006000000000008010001000000004000000000000020000000000000000000000000000000000000040000000400080000000000000000020000000000000040000020000000000000000000000020000001000000000000000000000000100000000000010000000000000001000000000000000000000002000000000000800000000000000200000000000000000000000000000000000020000000000000000000001000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x8b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e",
+ "transactions": [
+ "0xf87981b30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdd0a69ca9a6c3977ae1734d40175aa0720a866ff9353ce4aadfd8a4cd762e53a0290a5ac57e2f318959aaadec811bf9f8017191594476415923ddafef9a25de7c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np224",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa0a11d77a69e2c62b3cc952c07b650c8f13be0d6860ddf5ba26ef560cefd2000",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x8c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db",
+ "transactions": [
+ "0xf86481b4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e55768f282e2db5f2e48da696a07d1bff5687ca7fa5941800d02a1c49a4781b4a00eb30d56234ac991413000037e0f7fb87c8c08b88ae75aa33cb316714b638e1b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np225",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd8287e5675676595007edfbfff082b9f6f86f21bb0371e336ca22e12c6218f68",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x8ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81b5010882520894f031efa58744e97a34555ca98621d4e8a52ceb5f0180c001a099b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348a056e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np226",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e3c75d8db0bd225181cc77b2ec19c7033a35ba033f036a97ba8b683d57d0909",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x8d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1d",
+ "validatorIndex": "0x5",
+ "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np227",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xacca3ad17c81310c870a9cf0df50479973bd92ade4a46b61a2012fa87c7b8a0f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x8de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177",
+ "transactions": [
+ "0xf88281b608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05147ab82c47d0c6f6298c21b54a83bc404088dcf119f5719034a1154f2c69acaa035070fffcba987b70efcfc6efbf5a43974de5e11331879bbfbfe7556915da7b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np228",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0468ebde6657b86a2f1561ae8ef57c6cbe23b7dc08cc0ad823ea3831388e1691",
+ "receiptsRoot": "0x591e45121efd9a319ad048f68a35db27c69b829a65d0c7817224a1c5071ab327",
+ "logsBloom": "0x00000005000000000010000000080000000000000000000000000008200000004000002080000001000000000000000000010000000000080000000000000000000000000000800000000000000000000000000000000000000000000000000b00000200000000000000000000200000000000200001400000000000100000000000000000000400000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000020000000010000080000000000000114000000000000000000000040000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x8e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72",
+ "transactions": [
+ "0xf87981b70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04ccccf5fa7c7ed5b48d30bee3e8b61c99f8ff9ddecff89747e5685b059d70fa7a042982d8d2a54f9a055fd75df65488462a0ceae67b8a80966427c5d7ea1cf563b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np229",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9f5936ddc444db8ba3787be50038f195ddb86663f39b62d556f7700334f441d1",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x8f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663",
+ "transactions": [
+ "0xf86481b8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07cc4f254afaef8c4953d8a30221c41a50b92629846448a90a62ebdc76de8b2eea073f46d5c867c718486a68dfdf1cd471d65caa8a2495faba0f0a19ca704201e1b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np230",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x57dc2fdfe5e59055a9effb9660cfc7af5e87d25a03c9f90ce99ee320996a1991",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x8fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0",
+ "transactions": [
+ "0xf86781b908825208940a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a01808718e5bb3abd109fa0d2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353a0542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np231",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc6a8588f5fa71465604ccee5244d5c72a296994fb2bf1be478b664bc2aa77c39",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x906",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1e",
+ "validatorIndex": "0x5",
+ "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np232",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x38cdb4e70eb9771bab194d9310b56dbfcba5d9912cd827406fff94bddf8549d3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x910",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098",
+ "transactions": [
+ "0xf88281ba08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a06f8db09016d87e96d45d0835a60822fb305336ab1d792944f6f0aa909b73c9d7a01da7c6ba739bf780143672031e860f222149e1e6314171737fee23537a1e7f0c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np233",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbf1db5dc400fd491fad1abd61287f081ebd7398c76f20ecc0a6c9afb30ba5508",
+ "receiptsRoot": "0xed257fe243a1ffa922e5a62e40ffb504d403afc1d870fdcacd7f0aaf714e9ca1",
+ "logsBloom": "0x200000000000000000000000000000000000000000000000000009000000800000000000104010000000000000000000000000000000000000000100000000080008000000000000000000800000000000000000000000000008000000000000400000000000004040000000000000000000002000000000080004010000000000000000100000000000000000000040000000000000000000000080010000000000000002000000020c0000000000000000000000000000000000000000000000000000000000000000000000000000080000000080000000000000000000000000400080000000400000000000080000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x91a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9",
+ "transactions": [
+ "0xf87981bb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ef0e59c1798c0a7645f75f893cf81eae4aff9f49159b7365b8d4e907367f91f6a0095a58cb4d8be1816acf8b4e11f9d9b2a03d3f392eee1f19bea70b50ed151584"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np234",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5b75a7bfd5eb4c649cb36b69c5ccf86fecb002188d9e0f36c0fdbc8a160e4ac6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xea",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x924",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180",
+ "transactions": [
+ "0xf86481bc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a078dfab2121885d4181d63c7088757f7feb65131b155ad74541de35c055c31ec3a005cccd843ec8a535a567451c3b5034e05bac10f9328c63aa0b4893ee4f910ba2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np235",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3f130c3409ad205204d14e6b5be4ccf2e65559d39cc98dfc265e1436990e5964",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xeb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x92e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81bd010882520894f8d20e598df20877e4d826246fc31ffb4615cbc00180c001a0c982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350a07a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np236",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1ad56a036d6b544ee8f96f2d3e72dfdb360fa3c81edef33dd9e9fc1779d174a4",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xec",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x938",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1f",
+ "validatorIndex": "0x5",
+ "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np237",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf43c19d64439e20deb920de4efbb248d44d4f43d0dfecd11350501bc1a4bf240",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xed",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x942",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e",
+ "transactions": [
+ "0xf88281be08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06ba7d56fdfaf77a1a66bfef9529419b73d68fc1aa9edef961ac3a8898f04e5caa054635ee7b91858d97e66944311c81fd4f57d328ee4fbdf8ce730633909a75f01"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np238",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05a62e01803a967ff89e7e9febf8d50b1b3092aab5580c7f85f465e7d70fef3f",
+ "receiptsRoot": "0x294eca38bb21bd8afeb2e5f59d0d4625058d237e2109428dfb41b97138478318",
+ "logsBloom": "0x00000040000000001000000000008000000000000000200000000000000000000000008000000000000000020000000040000000000000000000000004000000000000000000800000000000000000000000000000000080000000000000001000000000400000000400000000000000000000000000000000000000000000000880000000000400002000000040000000000000000000000000000810000100000080000080000000000000080000000000000001000000000000000000000000000000080000002000000000000010000000000000000010000000000000002000000000800000000400000000000000000000080000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xee",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x94c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1",
+ "transactions": [
+ "0xf87981bf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0548377761079f73162f83bdc2cfb09dcde9e08c8db66d4d983f1856c5145fe6fa06b2bd1223fbb1b72016150f57bc7ae1f8cce5c0fd301bb9216bb804c89bf0a97"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np239",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbca1fef6bcfcbb170b7b349f92a3b92fe03296dac1fd64ccda295c496a261a16",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xef",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x956",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681",
+ "transactions": [
+ "0xf86481c0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08cfe044eb5748d538f72e560c45c7a01f94f4b7c6e9b1245bade89c0d97f9932a02b21fe651e5fb05d1f8de320dcf8cc037b2c0e989793f6b445f397c77f42a4f0"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np240",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x82a80ad266f2a1539a79b2dcf8827aabedcc1deeb6cfb4869a8ed2ea26923726",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x960",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3",
+ "transactions": [
+ "0xf86781c10882520894fde502858306c235a3121e42326b53228b7ef46901808718e5bb3abd10a0a03d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34a04278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np241",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x59b60dbf89d7c0e705c1e05f6d861bfb38bec347663df6063be9eb020e49972a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x96a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x20",
+ "validatorIndex": "0x5",
+ "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np242",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e5d7390e70d057c7dc29e173e338e7285e276a108eaecf3164dc734ce2fd9b5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x974",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f",
+ "transactions": [
+ "0xf88281c208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0057b9bf7b2b99c50cf16c0b995e2846ba833edc03f6efc1b97566022651cabeca0237b38f74a2a8c39a2c344ef2d7fe811c37cd20ed2f4d47bfc38d896f3c9db75"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np243",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8725e2687d45a52ad320e82b90e009b1aa5effe7ebfe994116afa25daa09468f",
+ "receiptsRoot": "0x2f9d61b38064fb9da0bb0f93ff73e1021c62ba761714e96a6674cd927bde4f9c",
+ "logsBloom": "0x00000000000800000000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000040000000000000000000000000010000000008000400000000000600000000000000000000800000140000000000080000000000000000000000200000000000000000000000000000000000000000180000000000000000000000000000000000000000000001000000000000000000100020000000000000001020000000000000080000000000000080000000000000000040000000000000000000000000000024080200000000000000000040000000208000000000000010000000000000000001000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x97e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0",
+ "transactions": [
+ "0xf87981c30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017b61104ac6d28f1262b3750475b328dfd50f8496e0772bf19047d9d1ee9e56da01aed9f9280926e68fb66065edcf80320cab6f6d7c7af4bc8d9d007e1ea6a168d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np244",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc5f9b1665244a32dc0885794d5aaf3ce0b464eed1208412ca14abcfe4b908f64",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x988",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606",
+ "transactions": [
+ "0xf86481c4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a93d446ef64bccf6c88d5285e78e7625fd5c9ac9c8aa11ad45db01b95b6694a5a0761620f10b11ee3cc1932adf95133349f5107aed7b8c150192fa89665ecd7552"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np245",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5bacfe50ff7f0200bc1a4ea28e3fbe1a269ea7cbdbe7fb5d83bde19774c92e7e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x992",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81c501088252089427abdeddfe8503496adeb623466caa47da5f63ab0180c001a0deade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25a065f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np246",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1c407d215d7fa96b64c583107e028bcf1e789783c39c37482326b4d4dd522e05",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x99c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x21",
+ "validatorIndex": "0x5",
+ "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np247",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x16a2c4f318277ea20b75f32c7c986673d92c14098e36dde553e451f131c21a66",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x9a6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288",
+ "transactions": [
+ "0xf88281c608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02648ce9c5825b33559225aada97c08de484ab8282549d90cfc1e086052c22be8a02054d7eeb1e8bf4ab25b2581ccb0b0a3500625cf7a0315860202eb2eaf094f9c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np248",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x291c5ca9a114bdb7bf296b4ff4182b930dc869905eaa1219cbb5188e8feaa9ab",
+ "receiptsRoot": "0x9f35106348d01548df28e681773a27cffe40648e4d923974e4b87903f578da11",
+ "logsBloom": "0x00000001000000000000000800000000000000000000000000000000100000000000000200080000000000080001000000000000000000000000000001000000000202000000000000000000000000000002000002000000000000040000000000000000000000000200800000000000800002000000000000000000008000000000000000000000000400008000000000008000000000000000000002000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000181000000800000000000000000000000002000200000000000000000000000000280000000000000000000000000040000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x9b0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a",
+ "transactions": [
+ "0xf87981c70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09f49a6018e3736ea3599def5663a57cfe19cb3f27bfdd80657503262a5bcfc87a02a26782058025cfe1205be964cc9ac31cdf510a8a9f867bff2317275b13ed02c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np249",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x359fe6cc7b7596b4455fdc075bc490d3697d4366c39c40dd6fc935da0ceac7e7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x9ba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf",
+ "transactions": [
+ "0xf86481c8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa043e1ad9aa519d9a1e8a15918ee6bbc0fd98061db6058597bd984098600495f96a01d5edd1b3fc3b45ff2a17a9c7eee3ad4c75e24fc090a4a0e48f39da49e7ad263"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np250",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc73008737d0cfdbec09b3074d48f44e406f0598003eab9a1f4c733de38512855",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x9c4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6",
+ "transactions": [
+ "0xf86781c90882520894aa7225e7d5b0a2552bbb58880b3ec00c286995b801808718e5bb3abd109fa00968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694a060f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np251",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x693db83454936d0dacd29b34de3d2c49dc469bbe4337faec428b028e0d967642",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x9ce",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x22",
+ "validatorIndex": "0x5",
+ "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np252",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd358fe0baedc04a81fdaf6cdfc71c2c874291e47d16dd51cc032f0678078a009",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x9d8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb",
+ "transactions": [
+ "0xf88281ca08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0941941ac43420c855cda955414a23d3bad4d0f2bfbeda999250f2f87d228878da0357223781ec5d666a8d5e8088721e9952f00a762d5fc078133bea6bc657c947e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np253",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcb19946b2b5a905882151fff9a12cce6e4c3be46f7da6b67263b0cc781fbe80a",
+ "receiptsRoot": "0x9b15dea2f021c6c74dc60deea77fd6a1ce29c9efc2596cbaaf73ef60370a03e3",
+ "logsBloom": "0x0000000000000100800000000000000000800000000000010000000000000000000000000000000000000000000080000000000000000000000000400000000000002000000000000000000000000000000000000000000000000000100008000000000000000000000000000000000020000000000000a004200000000000800000000000000000000000000000100000000000000000000000000440000000000000001001000010000000010000004000000000000000000000200000000000000000000000000000000000000000000400000000000000000000000200000000000000000440000000000120000c00000001000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x9e2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b",
+ "transactions": [
+ "0xf87981cb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06fb97cf9fb9b8f7159a9dc549e412001ca969f0dafc3c9294b0e081741aa3d9aa003ed12873ddb354ccf7b0f8e511136ff335a8e4ff6bb7f93ce19e097970c9774"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np254",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x907ae262cf7f9a93ecd0d1522c6a093ffe39594b65ec185c5059dfa7b3394371",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfe",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x9ec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55",
+ "transactions": [
+ "0xf86481cc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a082f832d1212a980978d5716dca8820344200eb6967b24adb2bd112a896b4dda3a0393b965bcf272398cdd6de788c3aa929a67a42466883a472538fb1dad06c07ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np255",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc39a9999ffd22de07bcf6a6a16b5cf1da7675dcb135e3503111a1dd50913cf0c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xff",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x9f6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81cd010882520894a8100ae6aa1940d0b663bb31cd466142ebbdbd510180c080a054eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32ba059af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np256",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x979018c4d3a004db4c94102d34d495dd3a4dc9c3c4bcd27d1a001f8095384208",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x100",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa00",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x23",
+ "validatorIndex": "0x5",
+ "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np257",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55e1fa04203cc0edebab3501d9552eaf0ac3bba421bf3480a50e1549cd479dc5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x101",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa0a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc",
+ "transactions": [
+ "0xf88281ce08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08a7526f8f209ff44329b503a7d726f569b861894584401651a83668be3971cbfa040314bdfa618ead4fa21933ed3a8af7e814620e3befa914828b981b391096441"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np258",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d05cad792af190bb84ad7a0bebd232c433cf16b90cffea9f4f824d562ec0eb5",
+ "receiptsRoot": "0x7b32e50058711e6aa1981f911bb5fb6bd05182c7e7850480874c3754788e5ee2",
+ "logsBloom": "0x000000000000000000000000000000000400000000000000000000000200000000000000000000000000000000002000000000000040000000000000000000800000000000000000000080080000000000040000000002002000002000008000000008000100000000000400000000000000000000000000000000000000200000000000002000000000002000000000004000000000000000000000000000020000000000000000010800000001000000000000000000000000000000000000000c0000010000000000000000000000000000000000000020000000000040000000000000000000000000300000000000000000000800008000000000400000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x102",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa14",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1",
+ "transactions": [
+ "0xf87981cf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1c9705b3794f376d02943123846aaae435a6590ddb802e16e91f87ae13c910a0609129061ec7d065ea3c154152c452f76a7894f2459c42c33675af6a20c9ad3c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np259",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x06ffd1eba12cda277819f77a9a89a4f78265f7aed5158dc51332218976856e82",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x103",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa1e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632",
+ "transactions": [
+ "0xf86481d0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07de64020fd82a08d2737ded6967d6a6095c02858161988f0626bad7dd2238057a00ad64af462ef2241d4e4c0da1dc108871126cf2aa2b82afd98d7069fc79d9085"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np260",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3d72e9a90b2dbfc909c697987538e4e9a8f2b127a783109fbb869bf3760bd7a0",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x104",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa28",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f",
+ "transactions": [
+ "0xf86781d10882520894a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e01808718e5bb3abd109fa004c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2adea05e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xafb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np261",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c514217bbc30325a9d832e82e0f1816cff5d7fed0868f80269eb801957b22a0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x105",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa32",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x24",
+ "validatorIndex": "0x5",
+ "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np262",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32fc9182d259ea7090be7140ec35dee534b5e755af25c3a41b2fe23452cd75ae",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x106",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa3c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f",
+ "transactions": [
+ "0xf88281d208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0010b2ab5421f3fe86f38332dd1c862ddcfc711b2255d8f2a677985d3858b643aa025f4fec49790d44c9b50ed1bea3c5700de165dc239173328e0d0c045f0dd4558"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np263",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdbed2b577f83fcb221ae85377d9c4f41b8ca95de085a3a697098ceaa937d23f8",
+ "receiptsRoot": "0xf4e79fec628d38bdc719707be2f797b74efbc9468ba5a3ae9415877e11c21db4",
+ "logsBloom": "0x00000000000008004000000000000000000000000000000010800000000000000040000000000000020000000000800410800000008000040000000000000000000000000000000000040000040000000000000000000000000000001000000000020000000000000400200000000100002000000000000000000000000000000008000010000000000000000020004400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000008000000000000080010000000000000000000000000000000200000000000020000000000000000000000000000020000800000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x107",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa46",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5",
+ "transactions": [
+ "0xf87981d30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0aa1f3a14b2bee05c15deffd1fcbad6d16deb140557251b04ddb61574fa8c70d8a0614a539b7fe8c276d26cabc1ff36c88c3f6b9cf3bc8836309a1d3f46626b5153"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np264",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2eb443ed50d07a6b1dbb2c154cc221cfb0475593b39ca2d3569224ea7a08030e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x108",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa50",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc",
+ "transactions": [
+ "0xf86481d4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0533560fb23c458df00902dbacef307e98096d91f179c49458d99e2eecaeaf3d3a0314508cba155f195ff77eff1a25ed4f454a07b404ac82d3ea73796bd9af3128d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np265",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6e68dd5ff68bf8a325446716e5bc1629a4e77167c3b5c9249ac2e440b35dea9b",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x109",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa5a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81d5010882520894ac9e61d54eb6967e212c06aab15408292f8558c40180c001a0898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100aa07e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdf979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np266",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4783eb369238bf2856e00bbc632735adf5ea404b766a0a70c27913314e170bac",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa64",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x25",
+ "validatorIndex": "0x5",
+ "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np267",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd0b9db5bce164e65b476f578ff93039bad1be78c8d1f595ff8496c2f7a67fea4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa6e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea",
+ "transactions": [
+ "0xf88281d608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa03329c0816ba8af740dd07a393681abfd26c3f0a121cdfa2390607d0d1832e741a051d0d0b427004563def4552ee51b81a2ca1f41bb48e8b9ae20615381c353d9b3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np268",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcb8d1404a32030e577a2628884f57433fe91b36b838f8576471bc36d87784132",
+ "receiptsRoot": "0x65c1a0ac45edc227576188f00c72612cd6c4d27cdac8d997bc6c9f499d21565c",
+ "logsBloom": "0x00000000020000000000000000000001000000000000000000000000402000000000000001000010000000000000000000000000000000000000000000000000000000000800040080000100000006000000000000000000000008000000000000000000000000000001000000000000001000040000000000000000000000000000000000000000080000100000000000000100200000000000000000000000000000000000080000000000000000000040000000000000000000000001000000000040000000000000000000000000000000000100000000000000000100002000000000200000000000000000008000000000000000008010000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa78",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01",
+ "transactions": [
+ "0xf87981d70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0310faf1dfcbc5597e207ab627226d2deeea1eedec7ffd8e68740fb76545586d1a01919f4683f202d4ccb3ab524d89d11119e7115645707333703d70f6fbe3c610d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xedad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np269",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0199e03e7400c428fb1bba7126f4eb3a12becd96c4458bff54952e5535b4a3d0",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa82",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e",
+ "transactions": [
+ "0xf86481d8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0ea5ad6553fb67639cec694e6697ac7b718bd7044fcdf5608fa64f6058e67db93a03953b5792d7d9ef7fc602fbe260e7a290760e8adc634f99ab1896e2c0d55afcb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np270",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xad6e3dc4bf8e680448a8a6292fc7b9f69129c16eb7d853992c13ce0c91e7d1ce",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa8c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0",
+ "transactions": [
+ "0xf86781d90882520894653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c01808718e5bb3abd109fa0f1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466ca02043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np271",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4347088d10fe319fb00e8eee17f1b872f2e044cbe1cb797657294404bf370e30",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa96",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x26",
+ "validatorIndex": "0x5",
+ "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np272",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9c73e0cd551b43953f3b13ee9c65436102e647a83bfefa9443ad27733d0371c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x110",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xaa0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4",
+ "transactions": [
+ "0xf88281da08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0972f048bcd4f8e2678a209e354570de7452fa342744fab1e44b7af67b2484d9ea0076f82074ff9697256d2661ad9f9a7321ff54fa3100ecc479166286a9a22ada5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np273",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf003762d896629dcd3a92a67ee13b96b080f4a3e71402a1dcbf9f444377329b5",
+ "receiptsRoot": "0x4d68fb9bfae6768b9578f5a63f455867ea5993ec2261fad2a25b45794d092f7c",
+ "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000000080000000000000100000008000000000000000800000000000000000000000000000000000000000000000400000000040000000240001100000000000000000000000000800000000000000000000000000000000060000000000000000000000000000040000000000002000000000000000080000000200000000000000000000000800000040000000040000000000000000000000000000100800000000000800100000000000000000000000000000002000800000000000000000000800000000014000040000000800000000000400000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x111",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xaaa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0",
+ "transactions": [
+ "0xf87981db0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08883be3af4b0a273883412ad320e6dcace1f505d9b20194e8f9e2e092c8d5ce4a03da92647d3d92d2868d5b9c479d98faf263e78eb67f259101a65ff56ee1eccbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np274",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x741d337861f144fc811cfac1db596e3bedb837b0fb090a3d013e5492bf02b233",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x112",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xab4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac",
+ "transactions": [
+ "0xf86481dc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0bcd2b139343048e9174e86251017c9b7c4da9fc36e4a84cf98eaf3855561f8e3a01c25a7b3ff3ebd7d9cbed5aa65515f8ba06fb8860d0764a98591da24e7d1c842"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np275",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1ce5b13d3189869321889bb12feb5da33a621bf0dbc4612b370a4b6973201f7",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x113",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xabe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81dd010882520894d8c50d6282a1ba47f0a23430d177bbfbb72e2b840180c001a04330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85a07977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np276",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x76aa5a1d0fc7c2f7e01a8c515f018e30afb794badc14b5d8e3651096458947a0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x114",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xac8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x27",
+ "validatorIndex": "0x5",
+ "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np277",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaad6081261920a2bddee7ad943a54ceebdb32edf169b206bd185bd957c029389",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x115",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xad2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309",
+ "transactions": [
+ "0xf88281de08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a092ec956d91708337ef4625bb87caed7a2bab63e40c8e65e8c9ee79a89b525b53a02bfff0c6dadfbf70dbd9fb2d75a12414d808ee6cce90826132d63f8ef2ce96b5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np278",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac5c584edba5f948690abb0f1c0f9bef685dec896c8f6c5c66ef8dd65810d53e",
+ "receiptsRoot": "0xdd1d7486ff21ad1c1e17b4d06cf0af6b4a32f650ac495deff2aae6cb73338de3",
+ "logsBloom": "0x00000000000000000000002000000200400000000082000000000000020100000000000000000000000000000000000000000000000000088000000000000010000000000000000000000800000800000000000000000000000000000000000000000000100000000004001004880000000000000000000000000000000000480000000000000000002000000000801000000000000000000000000000000080000010000000800000000000000000000000000000000000000000000000000040000000000000000000000000008010000100000000000100000000000000000000000000000000000000000000000000000000000000200000000010000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x116",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xadc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c",
+ "transactions": [
+ "0xf87981df0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa099b6473bcd99e0f32d82c046bad2e1824a8468bae8347768d907768e2fe64a2ba051f3f8b7323eab23d5543c8e372e4e184bc3ee108eab5455b89d40d9cbc23008"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np279",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x909007de8369b2fd9597dd7b84ab31e36b949026383fa8957befdba94703689b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x117",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xae6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87",
+ "transactions": [
+ "0xf86481e0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d8414a9d94412185c316893b53c874ae28ad6c0d67910ec66b39051f7842408ea05329ebb7080c9a6ae9372e8004706b78f7465746c3492816b6255fcba4d84979"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np280",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4dcb18dbea7ec4b9dc13b208172da29eb275e2095a6f8c6aeee59d62d5c9dd76",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x118",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xaf0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa",
+ "transactions": [
+ "0xf86781e10882520894b519be874447e0f0a38ee8ec84ecd2198a9fac7701808718e5bb3abd109fa0cfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690a01e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np281",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcbbdc9e51f0cde277f8f0ba02544d4d2be87cb7a5853a501524d760b00ec5e57",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x119",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xafa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x28",
+ "validatorIndex": "0x5",
+ "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np282",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5f40d100045883afd309122196cd37e687124adc5ec4c609e9d4ea9e8050be1",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb04",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382",
+ "transactions": [
+ "0xf88281e208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a02a4dd1a40886d389cecff4ca095a57e2f1e924b8d0e80e95c67961bec5af4b34a00adc6e41c4fe22eb93c7bc6ac529c405a8beb3b75d3f82a24029c560d293bee1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np283",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7a69e46d9beb12acb2476f649cf7fa7d31624c8b521351b533e302290b7ce166",
+ "receiptsRoot": "0x8f6545857c380d6f9aefa3a76d16cc79ce6d3e8d951a9041f19d57cbde82f55f",
+ "logsBloom": "0x00000800000000000004000000000001000000000040000000000800025000000000000000000000000000020000000000000000000080000008000000000000000000000000000000000000000041000000000008000000000000800000000000000000000000000080000000000000000080000000000000000000000000000000000000000000000000000010000000000000000000000000040000000000000040000000200000000081000400000000800000000010000000000000000000800000000000001000000000000000000000200000000000000000000008000000000000000000000000000000000000000080000004010000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb0e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b",
+ "transactions": [
+ "0xf87981e30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ac71118aff6dbdfd117ed52c41169a3c1eec7c7b137fed7ec058a48916198f2da05b684d53b4cc1cdafdba987f894eb9c42da47785983593ee1318f8a79f83eff7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np284",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2d7b3e2f3ea5d7c34423a2461c1f17a4639b72a0a2f4715757ca44018b416be0",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb18",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa",
+ "transactions": [
+ "0xf86481e4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa088575e3574fdfafb5c288b553973607350d846bd81b304beddaa6ef3dd349eada03cacc2455d5296189c0fc6890380a3c405b96cecfc45dc04a7f7dafe76be64c9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np285",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdc0d40e96eaa22025544b17cc122fab8f236a1a5d0bfa1a07a6ea680fc31661c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb22",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81e5010882520894af2c6f1512d1cabedeaf129e0643863c574197320180c001a0c23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516a03f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np286",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d0b749b8735df89c9d0bd4fff2d180d87a7ff86301fc157573ff0e774a942fc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb2c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x29",
+ "validatorIndex": "0x5",
+ "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np287",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x06f453054ff02cd966887e3e22bf509aacb23ee18ca302b612f10d2fb473cfa3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb36",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee",
+ "transactions": [
+ "0xf88281e608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bac48741d1f314ffaab63f07d4e7a0bc34c68dde478b439f4bca7dcf0b0a1493a036448a9a4150cad5f24411e8a9bbe89096d555ad08818e90d524bbad8b380b7a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np288",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb45e7c8ace763c55943f9c73da1319566234dad9d29651d6b08227eb88c9c4fe",
+ "receiptsRoot": "0x490106e6f82f2847cc9eb542a9836943df09d8a6b2e4a4fafba322228449195a",
+ "logsBloom": "0x40000000000000000000100000000000000000000002000000000000000000000008000000000100000000400000000000000000000040000000000000040000000000000000004000002000000000000200000000000000000204000000000000000000000100000000000000000008000000000000000002000000200000000000000000000000000000000000000000000000008000000000000000010800000000000000004200000000000040008000000100000000000000000000000000000000000010000000000000000000000000000000080000400000000000000000000000000000000000000000000000000000040000200000000004800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x120",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb40",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869",
+ "transactions": [
+ "0xf87981e70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017d70f5a57065bf0973a62206ec4a9b7f1f329904de722faf30fff8e2dca5719a006d0438164dd0ff38d669ebaa44dd53cec0b81d8cfe855a9aedee94b3b1f724d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np289",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4c863fc026d042a28f4ee149361f77c9dae309e18ea2497255ae91f8c41e0055",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x121",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb4a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a",
+ "transactions": [
+ "0xf86481e8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0428b809dd6147da7fc27a9520ae39b6a361b8f646b4eae45b3b32e3e406d766ea00c794c60066a8d4e435ba368662d9a6c0ffdd57ec6c49fdb0c2d4c07a69875cf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np290",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4849e0698f5f4b970db7b185d122842a6f842611058a838fe4c48bf3c63b89b6",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x122",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb54",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e",
+ "transactions": [
+ "0xf86781e90882520894b70654fead634e1ede4518ef34872c9d4f083a5301808718e5bb3abd10a0a0953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3da004e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np291",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6334127515360bcab6eb39030e54b05d61d464576fb4f99fbece693ffa600610",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x123",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb5e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2a",
+ "validatorIndex": "0x5",
+ "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np292",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a53dd10b53014df9fed6a4ae0fee8fc21111c58421916e9c770906b7676cbaf",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x124",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb68",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d",
+ "transactions": [
+ "0xf88281ea08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04efd756d15757c98077f04c9f50a22f7e74b1f28f970614a6824b4a406c11d0ba01c4bc3461a415a9c4dbfd4406c3c684a5427ce1490c93d7a9f5e43891dedc709"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np293",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x82f613ee711de05f2cc6a4a107500bdd5045f1ba99ce2738222f343f6081efe6",
+ "receiptsRoot": "0x2c3a6865afbff0ff9319c72cb9974b085dfe9a34eb9b34e0f4bc267272a883ca",
+ "logsBloom": "0x00000800000000000000004000010000000000000000000000000000000000000180000000000000800000400000000000001000000000000000100000000000000000000000000008000400008000000000000000000000001000000004000001000000000000000008000000000000000000000000000000000000000000000000000000000000090800000000000000004000000000000100000000002400000000000800000000000000000000000000000000000000000000000000000000000000000000000000200001000000000000000000000000000000000000002000000000000000000200000040000000000008008000000000000000022000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x125",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb72",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736",
+ "transactions": [
+ "0xf87981eb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03cbaa69de647fe3ea352a6e71bab2ee53555fb8ab88c5e68efe28f2e5d687b9ea063c88d4e12b282eb4075d28f2fc6f36c7017ed0d91e36dbfd9d63a358e96abac"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np294",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x291d2f7ab3a39d6c34a1b1c66e69262273221f6a8b2bac448e37e64da2330694",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x126",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb7c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910",
+ "transactions": [
+ "0xf86481ec088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aa81d6aa3b28238a33a52a3e3b5f00fa2300402a222f10c0e7451318b3f81e25a0223f13ffcec992f0ed7592df411b58352aad6d277dd16e7d0a55e5ab5702a18a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np295",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe3e06a047edd89fc5a4f9ee475d8e10ace0a0bae37ad4df6613a6077870fcae4",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x127",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb86",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81ed010882520894be3eea9a483308cb3134ce068e77b56e7c25af190180c080a0190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60a02c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np296",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d04702ac0333be2a1e6ae46e4aa31fe4fe23f5458c6899a7fd8800d24162bc5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x128",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb90",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2b",
+ "validatorIndex": "0x5",
+ "address": "0x1c972398125398a3665f212930758ae9518a8c94",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np297",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb59802d3b42a67087c2362fe27807e97ea95f8894d734e3711d61768b0779cc5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x129",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb9a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87",
+ "transactions": [
+ "0xf88281ee08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a01a3bb1f736220feefc5706b013d9cd88f2e5d5c1ee3398b15ba14e84ed6a12c9a078068efcdcd82d92408e849bb10f551cc406e796ff1d2e7d20e06a273d27dfdf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np298",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18be7053419eb1d23d487c6a3df27d208a2f8973d17b6b3e78417df0d3ab1644",
+ "receiptsRoot": "0xa7318d908cd687d0e6d982ec99a33a54b0cb9d1bbe3782f31ae731231e79039f",
+ "logsBloom": "0x00000000000000000000000400000000000000000000000000000000000000000000000000000008000000000000000000000000040000000000800000000000000000000000000800000010000000110000000000000000000020000000000200000000000000000000000004000000001000000000000000000000000000040100000000000000000000000000200000000800040000080040000000004000000000000000200000000000000204000000000000000000000100000000400008008000080000000100000000000000000000000000000000000000000001000000000000000000000000000000001000000000000000000100000000800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xba4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052",
+ "transactions": [
+ "0xf87981ef0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dc80fe6320cc01dd2ab63a42dd099e2fa5e0a640e6ccdf8ed634ca0c7382bd9fa04b356107e6a61d8852e7dc24f02691a9bd203564fed22da46bc9d9cd560c3dd4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np299",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf704271ace032c151b512221e777247a677847e2588ffb6fdea3de9af775b059",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xbae",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458",
+ "transactions": [
+ "0xf86481f0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa06074cb58acfc1417684962272c546809696c6d2110b75735b19852066839a38ea03bd4f9b9b32c074215420391000ce0358e01e65745d7a6aa5513c4f857dd6579"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np300",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d6f0609afeda40249aad175bb482c3560b6f0e2fb612addd06c6f3953662531",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xbb8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6",
+ "transactions": [
+ "0xf86781f1088252089408037e79bb41c0f1eda6751f0dabb5293ca2d5bf01808718e5bb3abd109fa0e3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5a051429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xaa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np301",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4ebd469b936b8d119664429fa99c55d75c007d4d12b7eb4db058248fa52b7f46",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xbc2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2c",
+ "validatorIndex": "0x5",
+ "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np302",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e0e374db1e769d72af232e15f83b61024ab42a410b4088ad54ae31fb7ab24c2",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xbcc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b",
+ "transactions": [
+ "0xf88281f208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03f816a6f00b46ffee7ae7dc0a8472c822003d7f175c03fc883435b5303662e29a053e91a9fcfb952b9d2ee2d3017e3d02c8988bb4abcb9c343b66d90094e9b9817"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np303",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5cd39242444b2f075de43272eb00a7435191e5d07d4da17022f05f91167f8a71",
+ "receiptsRoot": "0x8c5ae4043b8c3ac3c3faf57678b01a0a80043b682d0a8ae2681dc5c892d7a562",
+ "logsBloom": "0x00000000000000008000808000000040000000000008000000010000000100000000000040000000000000000000001000000000000000000000000000000000100004000000000000800000000000000008008000000008000000000000000020000000000000000000000000000000000000040000000400000000000000000002000000000000000000000000000000000060000000000000000010000000000000000000001020000000080000400000000000000000000000000000000000000400100000000000000000000000200000400000000000000000800000000000000000000000000000000000000010000000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xbd6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d",
+ "transactions": [
+ "0xf87981f30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdff6973fabfb503b56e50264fa9d542805c351a2cf282d14e9a7e3f90df3bcea03fc2b2ef3d6e5c8d141f20dab6ea64a6ad2f7c5ab3da95c98cff7a73429036a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np304",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb8480fa4b2321e09e390c660f11ec0d4466411bae4a7016975b2b4fd843260dd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x130",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xbe0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f",
+ "transactions": [
+ "0xf86481f4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ceb79cfa45773ae766de6daf76c67f63fbf14c7cd3853b6cd9ba8cd7cd1608baa019c783f138465d2c59039c902cc9b90cbff0e71a09672939e2373390b1f8c4c5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np305",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x022e2901949be09d1a92be5055ced3cd0770b41c850daf830834dc7da22c9af3",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x131",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xbea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81f5010882520894f16ba6fa61da3398815be2a6c0f7cb1351982dbc0180c001a08dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482a02ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np306",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xec2a36c595c95a6b095a795e22415b66f5875f243697e72c945361b4f440c3bc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x132",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xbf4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2d",
+ "validatorIndex": "0x5",
+ "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np307",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x427bbc009fe03135af46fb83f7cdcf27c022159be37615c8caceff14061d2f1f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x133",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xbfe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250",
+ "transactions": [
+ "0xf88281f608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa07b4f78cff0cb04bb8cb3d81e0aabef7b54c34db7438322bc8c1554448a37b027a00b760535ea891c9b4af5c70ac5726b3829418f5b21632aa8dda9ed2a91a7e30f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np308",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4b11a079f7e911f563ce2c7a0bcda57feaea847b827bfceb4b0f0a1fde490e41",
+ "receiptsRoot": "0x2cea15106bcab9c8122ea9fc8d7b5ace9f0650a79134ad9732b933221eb0c440",
+ "logsBloom": "0x000000020000080000000000000000000000000000000000800000000000040000000001000000000000000000000001010000000010000000000000800000000000000000020008000080000000000000000000000000000000000080080000000000000000000000000200000100000000000000000000000002001000000000000000000800200000000000000000000000000000002000000000020020000008000000000000000000000000000000000000000000000000000000000100000000000004c0000000000000000000000010000000000000200000000000000000000000000010000000000004000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x134",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc08",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f",
+ "transactions": [
+ "0xf87981f70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03d6fef2d466b342db8155272b9e676d55fdc0fedab7d1fce3b3be54459203a44a016b740412be1021d3f480fbf75fa6733d5a233489a0e1cf72bf56c8b37a0ef80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np309",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d7fe7c7c5e17180dd3c5d11953d20c0df05569d83f29789680311e835d44c92",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x135",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc12",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955",
+ "transactions": [
+ "0xf86481f8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b82807e311788292f679bc187111f494eb67171b03e417afdfb54e17f53b9ecfa05d9e1261b6bd95693c5e7859fa6e9ac0f380083750f46dec3f5058026c00aa54"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np310",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x97742ddf818bf71e18497c37e9532561f45ff6f209555d67e694ec0cec856e7e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x136",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc1c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa",
+ "transactions": [
+ "0xf86781f9088252089417333b15b4a5afd16cac55a104b554fc63cc873101808718e5bb3abd109fa0f2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aaa0657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np311",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5feed3f1d6bc9de7faac7b8c1d3cfe80d29fbf205455bc25ac4c94ff5f514ca3",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x137",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc26",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2e",
+ "validatorIndex": "0x5",
+ "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np312",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xde4840156998638689e0d07c0c706d3f79031636ae0d810638ecdd66c85516f4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x138",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc30",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3",
+ "transactions": [
+ "0xf88281fa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06193bab90c2a0e05f830df90babae78be711ea74e7fa7da80fb57bf1eac7b01ba007568dc41c59c9a3e9f4c46ad8bac850ecee5fdbe8add1a840db65266062453c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np313",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fc93047d0ff562c8abee419aecf2b174b1c382f506dedcbb5ba04955cd985c7",
+ "receiptsRoot": "0xcd59afd93dd989872aa9f89197f533f1c6a90364b872e145f50ff782af2b758b",
+ "logsBloom": "0x00000000000000000000000001000000000000000000000010000000000000000000000800000000000000000000000004011000000000400000001000000000004000000000000000080000000080000000000000004000800000000400001000000000000000000008000000800004000000000000000000000000080008000000000040000000000000000000000000000020000001000000000000000000000400000000000000000300000000000000000000000000000000400000000000000000000000000000000000000000000400000000000000000000000000000010000000000000001000000000000000010000000000000000400000000040",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x139",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc3a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c",
+ "transactions": [
+ "0xf87981fb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0465ab07ff3930a9a8f24c5108701be4a0475480d72147e12305f9d67017af925a07b3dd5fbeae129ce4ea30381c15b2afd9be701e4969422415e07ecea3df82db1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np314",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcae6ffdf3092bcb2ebdc66df86177bce69bf2f5921e5c4d482d94f2fd5f6649b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc44",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c",
+ "transactions": [
+ "0xf86481fc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d92908e16f6965c17390bafa5649b05b9150b6db7cb63fccfa3d8ccc1f18ec7fa04082aba5936ac8d14c3f78d12f12d9437b575cebd82337c4499f2176afb74cba"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np315",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1220b41d89a79f31d67f2373ea8563b54fb61661818e9aab06059361fc1412ca",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc4e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81fd010882520894d20b702303d7d7c8afe50344d66a8a711bae14250180c001a067bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244a076661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np316",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x65c692f846c2dc380a912a71c1387fec7221a2b0fffae2451370c30ed15350d1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc58",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2f",
+ "validatorIndex": "0x5",
+ "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np317",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3dc5f82b5983ab440abc575ac26ea2f4962c8c31f7e8721b537ea53d385827d5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc62",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa",
+ "transactions": [
+ "0xf88281fe08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f5f035f73b86709cffa1134edc422e41e8ec49f3455943045c8571f4f12e8f6fa0659c80c0802ca16b9c71c90a8c1d7c32580b8dc2e33eb246d05e9c4920314a31"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np318",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb0a0edf94f736c11dfd920d0d386b5857441067979baff670d45380f5ce9c2b2",
+ "receiptsRoot": "0xbe0275e0c21d0b23665e6d0b34bbb1669b585dfb6ef89c0903dcf8586ec86d00",
+ "logsBloom": "0x00000020000000000000000000000000000100000000000000000000000040000000001000000000000040000000001000000000000000000000000000000000000000000000000000000000000001000000000000000400000000000002000000000000000000000000000000000000004800000000000000000000000000000000000020000000001004000000000004000000000000000100000800000401008000000000000000000800000000000100000000200000000000002000000000000000020002000000000000000000000000000000000000000200004002000004000000000000000000080200000000000000000000000000010000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc6c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859",
+ "transactions": [
+ "0xf87981ff0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03b9f00d5731e51c973193cb6169cb8024b864d02e5347f287f8de4807e343922a04763ef63ac8ddc3fab7ccc70a4890b69fc944f330f5dd92f1b0266aaa6730eb6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np319",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe7a75428fc4aadb70c1e0ac2ae59a54df93458845525804742ae02a83d4f235e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc76",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702",
+ "transactions": [
+ "0xf865820100088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08c4b5e491ee67e169155453cdfc9f7ee6f122aeda5d73caf8337d6c29be1be3ca06b9a4038e45c6b5e858787dda6d1fe8d3c502a42996b4fe1abd2de1b834cf5fe"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np320",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda3147e8c80cfa63013d1700016a432d64c00213231ac510ab15f7011eea14e8",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x140",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc80",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d",
+ "transactions": [
+ "0xf8688201010882520894dd1e2826c0124a6d4f7397a5a71f633928926c0601808718e5bb3abd109fa01f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6a01960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np321",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05dcc2c2d7e87e4e1d836888d7158131800d123c6b2de255ba83054dfa109b02",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x141",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc8a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x30",
+ "validatorIndex": "0x5",
+ "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np322",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5efe08d743bbae45240fc20d02ab6e38e923dedc1027cf7bc3caff52a138dc06",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x142",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc94",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2",
+ "transactions": [
+ "0xf88382010208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f8cf692109b242d13af60f7def7e34fc16e4589de28a3fc445e83fece028b046a07ab0d98800bffd516adf4a56b048f67b4d5ffcf438c8463d82a0fe41509f51e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np323",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe6408a88797a6a4177fdb082766f6f35cd304745d96ceec7ba85908cf887ba77",
+ "receiptsRoot": "0xf0fa46b5337f820bd96b8bf1a50706c91cf6e2d8a9bb0fd9859f0f80d60009e3",
+ "logsBloom": "0x00400000000000080000000060000000000000020000000000100000100000040000040000000004000010000000000400000000000001020400000000000000000000000000000000000000000000000000000000000100000000000000400000000000020000800000100000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000014000000008000000000000000000000000800000000004000000000000000000000000000000020000000000010000800000000000000000000000000000000800000000000000000000000000000000000000000000400000000010000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x143",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc9e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1",
+ "transactions": [
+ "0xf87a8201030883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04d42d5415cbd9d939ef53ef60dbdffb80d016dc6e0704059b94ea4c1d398a2c6a06276655ceed05dd6ed9d6adcb9bb38bf699ae5f7ad1d8e47871404cd3ca98a00"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np324",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x38475f9f9a763356a2e995dd7ff0e2b3376078bd3048aa3d25bfec5257e1cf3f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x144",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xca8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664",
+ "transactions": [
+ "0xf865820104088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0654811f90e5259072ba79ea3e5a6ca7bfe8659e198ded895d149d1fc2bfe0167a052842cb4b3a0b0f2d722ec25a5c948bb2b78c3cd2d750303a5869a8812f17eed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np325",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda41e628e9aa8c362284b556f48a4e3f9e3e0daec75c7950cd5d4ea75b9f8223",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x145",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xcb2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e8201050108825208941219c38638722b91f3a909f930d3acc16e3098040180c001a063adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98a056f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np326",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbcdb535ac430393001427eab3b9ff8330ae1c997c2631196da62db6c3c5a5a08",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x146",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xcbc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x31",
+ "validatorIndex": "0x5",
+ "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np327",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf54751e3cc778e70000823cc9800dbecaf86c60afe48ddd4f942c9c26f606d6f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x147",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xcc6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4",
+ "transactions": [
+ "0xf88382010608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0af7d5214c1fa8aff20cfd3e89d0db2ff361cf5c23dae0823c6719d9bd3c3a996a0581c85fafb49fa0753c67f65e6ad04871fab4a72a9bf5d9ab3bd7aa33b230225"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np328",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaf3502d0a6862e2cde40bbf084cba5e582a0ba3b3bc0beec6791a712c3d171e3",
+ "receiptsRoot": "0x52236ae99e7647366a3e31ba24153828332656ea5d242e422ffca1dbf576701d",
+ "logsBloom": "0x00000000000000004000000000000000000000001010000000000000000008000040000000000000000000000000000000020000200000000080000000000000000000200000000000000021000000000000400000000020000000000000000000000000000080000200000102000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000088000000800000000000000000000000000000000000020200004000000004000000000000000000002000000000000000000000020000002000080000000000000000000000402000000000000000000000000000000000000000000000000000000008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x148",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xcd0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a",
+ "transactions": [
+ "0xf87a8201070883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015a81314b3c04efc725ff998badcf9278fb668561e5f9cdd42336845be60ec6ea04c593cfd5526eaf42203a3e6b5020e612ddd4053fa3123f51ae02bf8dde98eb3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np329",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a4691469da94625b4626e0a10273a2854e342a71b0711acebc46c8553eb8f0e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x149",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xcda",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058",
+ "transactions": [
+ "0xf865820108088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f9f0dcc20f1b62b8c567ac92dc1fbf50908f8bcd504fff3a342de336052e66bea00d38043fb1b141dc3fa2b97eaf09bc490be62e1cf7c40b670503ce0fbd8f6dce"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np330",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x44248f33cb76fe58bf53afa7a07e7b3d1d1efb1dcde8379ba1719d987a4cb83e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xce4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547",
+ "transactions": [
+ "0xf86882010908825208941f5746736c7741ae3e8fa0c6e947cade81559a8601808718e5bb3abd109fa0edd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7da068cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np331",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x30f652c6dbb2b9b0f66b7031f6fd0a8c163866de7b7f33c3e8a0d1f9b37a6d20",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xcee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x32",
+ "validatorIndex": "0x5",
+ "address": "0x984c16459ded76438d98ce9b608f175c28a910a0",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np332",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7ef2bb0e7090f0d465ded8b1064d0aafb5da43bc603b3ae8e39b678616f22f04",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xcf8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776",
+ "transactions": [
+ "0xf88382010a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0b67083c09c180ffba5ddc095999eaacd6d2cec077395c58d882c7a0706954896a02aaa853bfdbcdac9eefd90ff627107b5ca67b0c3969f3a770a4545a3b9d01514"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np333",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xff5f5d4ea4c9cb2944bea27f92a309b59ac66d45d231125258186ad3fcd58b61",
+ "receiptsRoot": "0xd5a4c662356c2fb912cf7df7798aabe0c8598dd3918c2c7e05db6619b76d855e",
+ "logsBloom": "0x00000000044004000000000000000100000000000000001000000000800000000000000000000000000000001000000000000002000101000002000000000000080000100000000000000000000000000000000000000200000000000000000010000000000000000000000100000800800000000000000000004000000800000000020000001000000002000000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000200200080000000000000000000000000000002000000200000000080000000000008000000000000000000400000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd02",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c",
+ "transactions": [
+ "0xf87a82010b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0e65e3fb877a256ecdcf4de6dc51df2bd755e14acad6b24c68e7168dbdfcf77b5a017ffeb5a31596ad459195610c5c5e3f348468dab79d930d49cddc0601cd5a965"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np334",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc8b1d4c2863741606d2cb870ed951e27495def1661f5192eef61cea97b8cd79d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd0c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a",
+ "transactions": [
+ "0xf86582010c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa041e92995e25443285655d748126496dbe98874a5cee8a1f0e58ea9f6a650f862a07feb73712a079a889322fcb61999780dab187d69eef21757af3eb0c9825f64c1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np335",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x53e02e88b716b3d80f9cac4ea6e30497d8a5e0f2dc4df131a20a9ffb78fe8cda",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd16",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82010d0108825208949ae62b6d840756c238b5ce936b910bb99d5650470180c080a0025cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30a0193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np336",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6be6c01d240a951a6adb298d9cb4e7c9e5e8960540de958b4b458fcfa489bf36",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x150",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd20",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x33",
+ "validatorIndex": "0x5",
+ "address": "0x2847213288f0988543a76512fab09684131809d9",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np337",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd2cd6e558f19ab03db7ee9677a850741b4f1f763c3de94539a16d54c27f6cac0",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x151",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd2a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b",
+ "transactions": [
+ "0xf88382010e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a057a97e1fae6dc03c4a29ad01b4d2ebea7069f1bef844b28b92875346d4454c46a01f5821fcf724aa6b0a3b082a6462e5f191a3c5659ba1b66b82cd42cf3175ba59"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np338",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1531cb938cfb7009f343d7ce9de03c63fe99878807b1ec8954b3a29a2d630f1",
+ "receiptsRoot": "0xa8c44170e431c7d7adf58109a7dbb58eeb38a19244c8a866311ef3a45fd13dfd",
+ "logsBloom": "0x00000000000000000000000000002000000000000000000000000000000080000000002000000000000000000000000000000000008000010000000000000000000000000000000000000000000000000800000040000420000400000000000000000000000000000000000000000000000000000000004000000000000000000200000018000000040000008400000000000000000000000000000001000000201000000010000001000400000000000000000000000000000002002000000000000400000000000000000000000000000000001000000000000000000000000000000000000080000000000004100000101000001000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x152",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd34",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13",
+ "transactions": [
+ "0xf87a82010f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de79b818723588fa8952e0d007ef1e1db2240b355f4f0f69f2af9df6b3408407a00962c062cd7fc4b8bf627bab2c0a00349d7b1bfc6f7875ca3a18967ad30ff219"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np339",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd35f874d00597dfb19f0363bbab78f3356e12ec8b4ee89f2883285139d7a3c29",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x153",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd3e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea",
+ "transactions": [
+ "0xf865820110088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa083a20e0b736688ba1f10440def989495ff253a281368f0ca21154d327c0468b8a0119312bdfeff761612ef529e4066bd28b4ed46895e5b67593fb0a3a897d3aa16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np340",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfa5b72ef0354b0b53f973b5285234c441e1bbf86d26374dd3856b36627d5caa3",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x154",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd48",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8",
+ "transactions": [
+ "0xf8688201110882520894b55a3d332d267493105927b892545d2cd4c83bd601808718e5bb3abd10a0a073cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1a0388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np341",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac6b9759a537d44a1629532184219d1f658f68745491b27e81c87361e72ad602",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x155",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd52",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x34",
+ "validatorIndex": "0x5",
+ "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np342",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe579eb979cbfd580c19ef8583f73a0fda902ee0895903a767d544ade95c50baa",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x156",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd5c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99",
+ "transactions": [
+ "0xf88382011208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0874d69f306b86e76465f6f0ad314cadee41f0f0d1844d35408201c3b2f690de0a0698f29877cb7dec8ee91a42a74f0f5270cbb391836fdaeda1e0876d3c16177b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np343",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf9106c3c4fcc77588a382ba0c2f605f6e07fcc418edac1cdd7de3b0e70f81b9f",
+ "receiptsRoot": "0x07a001dcc7eec5d1e8aa3508d61fcf5d511b4f9b766801b63319aa423ef08c3f",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000010000800000000000000000000840000004000000000080000010000000000000000000000000000000000000000000000020000000000000000008000010000000000000000000000000000000100000000108000000000000210000000000100000000000000000000002000000408000000000030000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200008800008000008000000000000000400000100000000000000008000000000000000000000080000000000000000000001010000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x157",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd66",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214",
+ "transactions": [
+ "0xf87a8201130883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa084f91b21758f4c28d386fa99e8b7e126d27a1f9e293e5df2683057e09a9c6a2fa051772044b702ac375f615dc0d6aaa8c1d38c3ac2a830539d2ab62935c5132921"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np344",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19268b0f7992afe0cf1f3c0ac73b371ed7d9e79dddf0435b72bc45e1682a9c74",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x158",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd70",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a",
+ "transactions": [
+ "0xf865820114088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0904e2a23972254826c8f3f5efa2d39122f980811cb9dd3e5d2869618d458856aa00fd104e760443aa8abcbdfbf2263d45a32a7aec32e59548b3e73575bc21f0243"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np345",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ef70ee0614b3ae112271af4be70033c61a89f337aa527b8657df19422d94913",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x159",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd7a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820115010882520894b68176634dde4d9402ecb148265db047d17cb4ab0180c080a09f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59ba06a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np346",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbbec06f293095304adb3f03ba055fd08a691c89d5de1ade4c1ed31b9c6672989",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd84",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x35",
+ "validatorIndex": "0x5",
+ "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np347",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x169c28a15311ed314bc0a4529aaddacc79d5fd6becdaaae69276079408d57eda",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd8e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a",
+ "transactions": [
+ "0xf88382011608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a065a20271c4b6acc45c7e172465adcdc218b164c0936999de9bdd37c4a4c63fd0a003792daae8ab2be81df0df962c26697830d30af560c8a85a0fba05e5cfc82d66"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np348",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x704fde0fccaf5957d60018e958bfb8cc7bb7e77eed37cee3bdcdcca280b3b1fb",
+ "receiptsRoot": "0x0016ae7d40181cb711af89f17dc40dfb53384c5ef535847ae4982b1d58bfadd1",
+ "logsBloom": "0x00000000000000000000000004800000000000000000000000000000000200000000000000000000000000008000000020000000000200000000000000000000000000000000000000000000000000000000000000004000000000000008000000000008010000000000100008000000000020000000000400000080000000080000000000040000000080000000000002000000000000000000000000001000000000200000000000800100000000000000000040000008000000000000000000000040200000000000000000000000000000000000000000000000020000000000200000020000001008000001000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd98",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237",
+ "transactions": [
+ "0xf87a8201170883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a7fe70291d9f18d3daffb9c6845116569c9be21f8b04c47235999ad35c20a079a03ad45b41a4993ea744bb28012bae4998ad6e97da464162d4ce51810e442e3ccc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np349",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x898ac18f3ec544e0908e3a1c5434515aa421b796a41501b0474375f49fba30c8",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xda2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba",
+ "transactions": [
+ "0xf865820118088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0027208b707b49c8686502030a1029e738d91a7c0bf9dff86bb90ccda2e5fc158a04b1d06ac6269fc336d1e6d0bac45e82b7d47ca4c271c7fed3bd1c6599b4bd0c6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np350",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3a29d14904f05f088f4aede9ab588a53f6a54db4f43cd77f0227445a0d7c8386",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xdac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005",
+ "transactions": [
+ "0xf8688201190882520894dfe052578c96df94fa617102199e66110181ed2c01808718e5bb3abd109fa0020ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1a00f72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np351",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x693ec0330efa3e07b25a9a758d30a43389876e03846885dda5cdb009ff0e2674",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xdb6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x36",
+ "validatorIndex": "0x5",
+ "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np352",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc25a9e84540d654be4abb3e8581cd2cc7cf97e54895e7a62d08eb78431d3f244",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x160",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xdc0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7",
+ "transactions": [
+ "0xf88382011a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00df7ffb1778e645f4fc3b0e2236b34c038c43aacbbc43abc8d710c3fc33901e5a00d7d3d9cbc790b2e206b30639a4b55c1d2f3c2ea18c058a5085f16d72b50455b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np353",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x911acb703f25c08267716b25fc43b19bf4ce43a053393e6f1dce78c1cba8c485",
+ "receiptsRoot": "0x758b6a000deb6b7275c48ea96b2cbf580372445f0bc5b285eb764ed1800e8747",
+ "logsBloom": "0x00000000000005001000000000000000000000000000908000000200420000000000020000000000000000004000800010000000000000000200000000000000004000000002000000000000000080000000000000000000040000000000000000000000100400000000400000000000000000000000010000000400000000000000010000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000200000000000000000000000020000820000800000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x161",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xdca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d",
+ "transactions": [
+ "0xf87a82011b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c6d3e03aa8b0625a3225e077addb3cf47c9d061148da25021b22a0746083cc11a06176a93c704e6c5088e9d18cbaca7eab1de348207c2ba50083934c4e215a079d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np354",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaca595525f5aa4f17314e44a3fdc0dae0f4037a1ee0a12bfb1bec7b9219f8d6c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x162",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xdd4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0",
+ "transactions": [
+ "0xf86582011c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ad6f8d4d86d80157b67311edc959413ac3f525a5ec6334cc826125dfb1908b05a02e91a1d46e2df7c7eb4dc92224252298c66dbbf321fbb6c827a6e2d348277298"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np355",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa307681299c7c385c512cbf83195ee62d35d29487665eb57cf2698c1b3e82066",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x163",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xdde",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82011d01088252089433fc6e8ad066231eb5527d1a39214c1eb390985d0180c001a0167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1ca0269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np356",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb36926502e2ee904451fa5970a453aebe89f5bc25cd8c1dcae196810968617c1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x164",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xde8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x37",
+ "validatorIndex": "0x5",
+ "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np357",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x67558b87a732daed74e1b9ed7aef6326aabe984df466494d2fc59d9ea951c6c6",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x165",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xdf2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0",
+ "transactions": [
+ "0xf88382011e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b20886ab8d36222d79bf9dad933333062a51e71dbd6de720f872874edb727276a05f68ff1bcbb8019f43e4e37a481075cc5565512eb56d34ccb707e8aec00a4204"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np358",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x15bdc9a6fcc0d4d133bc86adbda378e2110d51fc60304207240f24f60d4fc99d",
+ "receiptsRoot": "0xf9f06ad2e1bbf826b5cbeabfd01d508c4d7bc0781b946c5afc105a2e20d9155a",
+ "logsBloom": "0x0020000200000000000004000000000000000000010000001000000000000400000000000000008000000000000400000000a820000000000000000004000001001000000800000000000000000000000000000000000000100020000002000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000040000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000004000000000000000000000000000000000140000000000000800000000000010000000000000000000000004000000000010000000000004401000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x166",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xdfc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f",
+ "transactions": [
+ "0xf87a82011f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c35e2924126964cdf4a8847f4cb4a870f24a4654de527a3dc9fad248d338aab6a00d9292c8e92050bebef84a83b3deacddf95a33015a3d284b578cb0f1621c5a70"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np359",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x21d7cc2931eed33ddb03977b7d99c97ac378c41ed2ac25331478cd1fbd583e7a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x167",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe06",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36",
+ "transactions": [
+ "0xf865820120088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aab9710502eb45f06f5470674b88b22c30fdc865a22c86a7095f355629fb6d11a01d905abe10e39ed037ad29a46a81d0af6d52d9de2d7bef20e7b02db8c1cf13a0"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np360",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x128ac2d4c23be8773c460ed383defee0e767a4fe0a55e9f600a60e0fe051735b",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x168",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe10",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04",
+ "transactions": [
+ "0xf8688201210882520894662fb906c0fb671022f9914d6bba12250ea6adfb01808718e5bb3abd10a0a0d3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7a0202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np361",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8f8fd676089911db9824cafe64222a854d4767d0cc5fded3fa1643f735afd80",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x169",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe1a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x38",
+ "validatorIndex": "0x5",
+ "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np362",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb19cdea25a29e5ba5bf0a69180560c2bcf35823b81d82d8b97499ad1cc22873b",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe24",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94",
+ "transactions": [
+ "0xf88382012208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa034e8481ee12e75836d1e4cc88aef813a6bc8247b73aeb7a466a1ce95bca6e5fea07585402e69f5856a5724a9e83a9bf9cf77bc92cc619489f9903f09b8c3530f24"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np363",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09f1a8d40ad941a3c47fd34c32682a0058f79387d467a7ebb5d957455aab9fb6",
+ "receiptsRoot": "0xde87ab5715c2af5f977bcf679cd4e771796d49365c3111487aba12fdb69483a2",
+ "logsBloom": "0x00800000000000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000008000000000000000000000000000002000000000000000000000000001020000000000000000000104000004000000000000000000000000000000000000000000800001000000040000000000000002000000000000000001000000000008400000000000000100000000000000000000001000000000000000040000000000000000010200000000000000000000000000080000000000000000000020002000000020000100400000000000000000000040000000000000100000010000000000000001000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe2e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e",
+ "transactions": [
+ "0xf87a8201230883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0317931eb522b3488621079d412251962cc5a02794939e3a3b0c94c92df0b4da5a001348209aa47bc1a55590243d5168b2beb06c929b46104d144ba526070b2e5ea"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdf880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np364",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96f076c6c4d61d649b8f9c4290ff81fad55bfebe6e171f2d2bedb4b941977873",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe38",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a",
+ "transactions": [
+ "0xf865820124088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0886d94140ef16f0079167a92ea5577d300a4e87982588af41676d8d9a7a7f043a0388a734d4f7a8eb510a5e7aba3141505773bd329a70ff438be40d7b378fdafa6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xadfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np365",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x208cc1a739ecf1c8aed87a70e4f580b28d06f7dba19ef679a4b809870c0e66a4",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe42",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820125010882520894f1fc98c0060f0d12ae263986be65770e2ae42eae0180c080a06563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210a00a96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np366",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf4a7f460684eacde84218991911d63333e89a5a8fe5293e43b2b283209bb7297",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe4c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x39",
+ "validatorIndex": "0x5",
+ "address": "0x19041ad672875015bc4041c24b581eafc0869aab",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np367",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x44f6e5c8fd3452b71ade752a742ca9f61626aeeaa20e89d47fe414d1df414745",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe56",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a",
+ "transactions": [
+ "0xf88382012608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00d5ce478373461565e41764365499cc4a43519643829503796c5453e1bc7ff0ea03ef00a5fe608838a9156d394317734b358ac026af08b33c2aabfea8e9d485dfa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np368",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7fd199408596db163d237e6d25f64b90ac2bc04158524e8baac5d55f881bb52b",
+ "receiptsRoot": "0x8d3f058248d263db5e6d6d78ddf91fd2ec0183f2bdf3e9e142af87a53388e526",
+ "logsBloom": "0x00000000000000000000000000000100000200008000000000000000000000000000400000000000000000000000000000000000010008000000000000000000000020000600000000000020000002000010000000000000000000000000000000000000080000000020200000000000000000000000000000000001000000000000000000800000002000000800000000000000010000000000000000000000000000000000000000000000004000000000008000000000000000000000000000000000040000000000000000000000200000000000000000000000401000000009800000000010000000000000000000000000000000000000808000000800",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x170",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe60",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96",
+ "transactions": [
+ "0xf87a8201270883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a008faafda0a060040eca56f846ecbd6a399914482c31359f1ec04c98cc476ce82a04d2b02adc2c947898fa00cbedb4532f471cb5eb92ee19a30697ddd0c713132e3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np369",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a2360860a67f9187f50f56201c50d2309c961a2b408072e7c3d069c8c1216cd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x171",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe6a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226",
+ "transactions": [
+ "0xf865820128088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0da49c9575be5d906d247a5f4f0574e76d1edb1368dbdda1b4a5b58fba3fca82da00fa1c561fc766acefeeabf085384962f2599b3ca6b02996962095eed297df611"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np370",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x971bbdee0e408ff826563636c5eccce30540c1cba590880849a72ac21f74a4e4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x172",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe74",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04",
+ "transactions": [
+ "0xf8688201290882520894a92bb60b61e305ddd888015189d6591b0eab023301808718e5bb3abd109fa0626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dda0074494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np371",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a239ffb7957e73c3eebeb33b01444599ddcd5861f1dfb4bbe31584061f11389",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x173",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe7e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3a",
+ "validatorIndex": "0x5",
+ "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np372",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xadbba859a71886f49ccd216fbc6c51a42a7a6eff927970b298d4e0f6e2a9597d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x174",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe88",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a",
+ "transactions": [
+ "0xf88382012a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa085c885407da43158c33afe4c9d10a846d4cf5bb820c70f019ff8b6ee9dfb027ba077c0e90a4a029bea55eadf3b0d39261b6204a5c1b8e5e80838ebeef5c9fd456c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np373",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe5a5661f0d0f149de13c6a68eadbb59e31cb30cf6e18629346fe80789b1f3fbc",
+ "receiptsRoot": "0x97965a7b5cca18575c284022cd83e7efb8af6fcf19595c26001b159771ffb0ce",
+ "logsBloom": "0x80000000000000000000000100000000000000000000000000000010000008100180000000000000200040000000000002000000000000000000000040000000000000000000000000000000000100000000000000000000000000400000020020000000000000000000000000000000000008000000000000000000000000000000000000002000000000000000000000000000000000048200000000000000000000000000000000000000000000000000000000000000000000000100000800000000000000000000000000000000000000000000000000000000440000000000000000121400000000000000000000040001000020000000000040000200",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x175",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe92",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992",
+ "transactions": [
+ "0xf87a82012b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03e8b18cd5d8c796e69f450a4c00e75d7e2d38cf9d25dd19e2033fbd56fbf4b84a0175ca19057500b32a52b668251a0aec6c8f3e1e92dec9c6741a13ffe3fb214cc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np374",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0a82334be200ef303c1c3b95b92b6f397df138b7e6eb23d830fb306996f1c79b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x176",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe9c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d",
+ "transactions": [
+ "0xf86582012c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0519fcc6ae02e4901d4ccfcd2b0560f06bf13478b459310ddaae39f44b7ed1394a03b529b53be6c0451a4b644f5031746cb1db62cfbe43b962da26aff507d4293ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np375",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8e7778cdef2ec78802c7431cdd44768e4a4f6d9c6cc494ae02dc20c10bc6eead",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x177",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xea6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82012d010882520894469542b3ece7ae501372a11c673d7627294a85ca0180c080a09add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fba021a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np376",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0b7ff239a80d7ca996fe534cf3d36898e55e3b4dbd6c130cc433dfb10d83c2dd",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x178",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xeb0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3b",
+ "validatorIndex": "0x5",
+ "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np377",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5cac010e2605b327b97a4ef6f78d4c65554588283336081d8ef497a3860fdbde",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x179",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xeba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3",
+ "transactions": [
+ "0xf88382012e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a015118995d271e570428c3c349d49390af0fd81d3217f90159fc25b9d0791d6efa018c1a844d5d3523ce37308f0cd2e46e8d6ef99a9eb750e7325ca2c67d59aaf85"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np378",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe908771dea594628e0f4d2b5d3354bbc6f9cfa04a97249657a74b792c3254b77",
+ "receiptsRoot": "0x8dc461a171023c5f8e3f5d78e0842291fbe7b0a502495a334a1bc98337a8a1b4",
+ "logsBloom": "0x00000004000000000000000000002000000000000000000000000100080000000000000020000000000020000000000000200100000000000000000010000000000000000000000008001000000000000000040200000000000000000000020000000000080000000000000000000000000000000000000100000000000000000000000000010000000000000000200000000400000000010000120000000010000008000000000000000000100000000000000000080000000200000000000000000800000000000400010000000000000000000000000000000000000000000004000000000000004000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xec4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4",
+ "transactions": [
+ "0xf87a82012f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0d0666f18210bb986b7239269bfbd56336376ed77bb97b56e15df7647c1f06fe3a0718dc6abdefe863e76f0c3c356364d456d34d399b20ed93b61ed93a77bccbe80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np379",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x197f321622808ee71925004345aaf99ac87a833c97ee852265b6d8be5c0656fe",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xece",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07",
+ "transactions": [
+ "0xf865820130088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02f7e9b19c96e60b8bd18eaadf71b049e0f204d42e826667e5b741041663c1963a01ff9a63ae688fc0c05047b819d1b8326c55f60b62f84658814bf35c63b3e5c65"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np380",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19c0d6f1bcdcb2c419bb69ed7f176bd58c4833c057faede354566c4e6d6e9f20",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xed8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1",
+ "transactions": [
+ "0xf86882013108825208947f2dce06acdeea2633ff324e5cb502ee2a42d97901808718e5bb3abd109fa0fd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24a0542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np381",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6c634927494436f7c4daaee4ea5c99813ec3066af379315b031f40fdf12c74d8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xee2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3c",
+ "validatorIndex": "0x5",
+ "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np382",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x04f641173e82bbe7455a3acd37242315859a80d9b4a19a56997645e31a1d1097",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xeec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f",
+ "transactions": [
+ "0xf88382013208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08bc9a47ee84ed9389b94c57e8c7014515fefd3e891eff0e1deac8cb1266cfb05a06612fac81c3e0a0b905873bb3f9137f9f8ae952344a174e4d425564b31851350"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np383",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2cc62d5cb6ca1b74dd31ced44a51655d15f0c67d9e8b4560584124ea91649145",
+ "receiptsRoot": "0x7288150e98b9056465e864af6976d5ec6de80da74cee77596b9a67de235177ac",
+ "logsBloom": "0x000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000040000000000008200000000000000000000000000000000000000000000000041000000000000000000000010000000800c0000000000000000400001000000000000001610000000080000200080000000000008000000001000000800000000000200000000008000000000000000000000000040000000002000000000080000000000000000000000000000000000000000000000000000000000000000000000000008000000000200000000040000800080",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xef6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe",
+ "transactions": [
+ "0xf87a8201330883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0f1dbbd841499d2a51db61a05cf4a7a5650fd83eafe8516d0ad49e99db40c0d13a0542104414214add483f5e7397e9b98e95d336d60ff2b661eabfc8125548df848"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np384",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf88d2d5d961b54872a1475e17a9107724ba2cd0ca28cb7320aad2f903dc74deb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x180",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf00",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a",
+ "transactions": [
+ "0xf865820134088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0922834adc69ced79913745b4a53a63ff0b0d73552c658f63c35b74fe831f1990a072af738962b2108e1e3e534c88145aa55764f2908bdbce0a4433ef88e3fbfb0c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np385",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x248cbc35df3f48575474369a9105962a22bff30f3e973711545bb9cae1e06dff",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x181",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf0a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e8201350108825208943bcc2d6d48ffeade5ac5af3ee7acd7875082e50a0180c080a03931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6a0215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np386",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x899d1787e12b4ee7d5e497ac1b07d460146316edd86d589dd357e4e39e6e50a5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x182",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf14",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3d",
+ "validatorIndex": "0x5",
+ "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np387",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fd59459f6805b1c3f35cd672f058d3f4215b8ba06217056195a249529106097",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x183",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf1e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3",
+ "transactions": [
+ "0xf88382013608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f68ef0be353bceb12bd978567947ea2ade48f275f8488d4d9089a6a5df54ecaa01ea605cad7ded16c6744be5446342cef46c0f802938d30db72ee4e35eb0ee726"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np388",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x87aa8da72c4f54683d4ddfe7592b17518075332583bf40a0af34b072e1b8d5ca",
+ "receiptsRoot": "0x6b2a7f9df51def8b942a27f69021bd8954a4d01182bc78fe20171ec738d6a1cd",
+ "logsBloom": "0x00010000004000000000000000000000000000040000000020000000000000000000000100208000000000000004000000000000000000000000000000000000000000000000000020000000000002000000000000000000020000000000000048000000000000000000004810000000201000000000000000000000000000000000000000000008000000000000010000000000000000000000000080004000000000000000040000000000020000000000000010000000000000000000040000000080001000000400000000000000000000000000000000000000000000000000000000000000000000080000000000000020000200004000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x184",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf28",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462",
+ "transactions": [
+ "0xf87a8201370883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a036602b451fdd27281014a28c261ac59feabe8c6730619162c51ccd6452e0efcfa01dbbc3cb987dd50dbb59072a156ce01b7825d252e5855249afbda11fd763436e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np389",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4970ca728c597509e3afb689227e843d5da3be74aea9719a756d65db2694b152",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x185",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf32",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5",
+ "transactions": [
+ "0xf865820138088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09a9bf09cafb07d6a97b972a3b405a1dd30dcd6945d9adda6cf921c211bc046e1a03c97b3b08d67e3ccfcb8408e39d2e0971761c1905fbd7028fb52a1f163fb92f3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np390",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc5da7efe2ca6d0468002914ea2c334be08121fb5450b4a1b74baf08e65115192",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x186",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf3c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506",
+ "transactions": [
+ "0xf8688201390882520894f83af0ceb5f72a5725ffb7e5a6963647be7d884701808718e5bb3abd109fa0a38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751a067c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np391",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7f1f4d793182771fbacb9ef07a0736edbe4aa2417bf775c7b499b35ad791575a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x187",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf46",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3e",
+ "validatorIndex": "0x5",
+ "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np392",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58f87e8c7ffa26035df5258225c492a17f353b2d33420e0ac5b5413f0c29be1a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x188",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf50",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d",
+ "transactions": [
+ "0xf88382013a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e60cd99574bb50b626cf0b20d73ece21858aba52609136e6e2dc420a9fdc00eea00aeff0a4419c24268d9784a1ae211927004d8dbbbda3c47c0d0e2d32178ce8f4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np393",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x14a7327b3cff203afe17f16aca0470fbe12cfac971c79ef9bd5b3ef71bce5591",
+ "receiptsRoot": "0x3b0559fd9e27f69f8a378d27e3b5a82f18881f307f49ec63f89ad4bae18a1ee6",
+ "logsBloom": "0x00001000800000000000400040000000000010002000000000004000000000000000000000000000000000000000000000000000000000040000000020000000000000000000000000000000000001800000000200000000000000000000000021000000000000000000000000000000000000000000000000002000000000020000000008000002000000000000000000000000000000000000000000080100000000000000000000000000000020000000000040000000000000000000000000000000000000000020000000000000000001000000000000000200000000000000000000004000000000000000000004000080000000020000001000a00008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x189",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf5a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6",
+ "transactions": [
+ "0xf87a82013b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa061705b5163977bf95976fb0d2f44c1c581d19de8f68084001ed516813a7f5785a07daeb176a18749f11e1cec56a72e988c8362c2e15b86a9c5ae3e2cb2ddde0ce2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np394",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x02eb8f611a78bed4123c7b1ec6ca3148dee547538828183756744882a58b6993",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf64",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0",
+ "transactions": [
+ "0xf86582013c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0463d74275ffee97deea0603bdab389823c88c03997f176d4c349514d78d4dbc4a06b9796eed221b40094ded3ec3fa9bdbf097561ac3f8a142fef5e2c894a8296de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np395",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe5d836ff1dc0a199a799bdb1aa945580acf9e06c96bd6b88cbc60903e5904b9c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf6e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82013d010882520894469dacecdef1d68cb354c4a5c015df7cb6d655bf0180c001a06faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07ba0656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np396",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8fc7b0893f25c43c0dd53f57c7f98653e86d2570923f1831840c09c7c728efab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf78",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3f",
+ "validatorIndex": "0x5",
+ "address": "0x6d09a879576c0d941bea7833fb2285051b10d511",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np397",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb87cec8c84db91856e9ae32af116b449b8cb1d61cae190a182aebfb85d691e8f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf82",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe",
+ "transactions": [
+ "0xf88382013e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0065cd2e05815fd9bf6e9aced9947d0c43feed03d4bd010ce93828c5e45a9b483a019449b8fc18e639f9c1d7b0adbd3941622d1f2e8127b82993e0f8bb9cdc2999f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np398",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe154fbe6ca3c192310dea977b202b7e57523be45dfb36cf46816f7b1b86c910b",
+ "receiptsRoot": "0x09e88b070a05aab53918792ba761837b32e299692e1ee33a27d3b654a45ea25f",
+ "logsBloom": "0x00000001000000000400000000001000000008120000000220000000000400000000008000000000000000002000000000000000000000000000000000000000020000008000000000000000000004000000000000000000000000000000000080000000000000000000000000010000000000000200000000000000004004000000000010000000000001000008000000000000000000000000000000000008000000100000000000000000000000000010000000000000000000000000001000000000000000000000000000000010200000000004000010040000100000000000000000000000000000000000000000000000000000000000020000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf8c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa",
+ "transactions": [
+ "0xf87a82013f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a017bd3457b4b843b788bd719c6e49a5efad177ca349fa23ee93130c68a6c123a6a0595becbedbd04d964a7e8ca826f50061e1b1f16bea32c966670f7dbcc63dbbff"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np399",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x771db9f41d228f8d3e1a33889cc04468bb9691860cbdbf28203d90713eed1fb1",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf96",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f",
+ "transactions": [
+ "0xf865820140088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0db06597d4b08ca3fef9b08c69896cef6505785b448bfd0e051ebc7616a2f5a1aa07ca5051c69a0dcb5fae23ba89cb806d860072426d2e450eda056e9e9d8ee360c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np400",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd210aa806d0d5c95200a88fcc329357fb03782cc236bdc5f184c80246391162f",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x190",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xfa0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f",
+ "transactions": [
+ "0xf8688201410882520894f14d90dc2815f1fc7536fc66ca8f73562feeedd101808718e5bb3abd109fa04a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836aa0598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np401",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf77d84bb9077b7805492805f09aaeac8fdd72dadaba54464256d1b9633d7313d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x191",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xfaa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x40",
+ "validatorIndex": "0x5",
+ "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np402",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c45d111367d1e2766e18c8ef100cb4cbdd1db4171d269d0dee91b7789bf302e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x192",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xfb4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658",
+ "transactions": [
+ "0xf88382014208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0bab2abc49f4f65119331667d5bd95daefb8eec437cb7950b46f1b9a890efd4b7a065396085f5f690d669006b05bab15614816e44cf88bf49fcdf0a5857f364e6a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np403",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xade6dd841f231dcce74ab564f55972731c7eb4a0b5c3ec1a64bb979f754b786c",
+ "receiptsRoot": "0x424252c901f76c684b72e2637c97666a35b4020fe9fd8add1bd00fc83cf57512",
+ "logsBloom": "0x08000000000000000010000000000010002000000000000000000000040000200000000000000000001000000000020000000000000000000000000000000400010000000000000000000000000000000000000000000000000000000000000020400000000008100000040000000000000014000000028000000000000001000008000000000000000000000000000100000000001000000000000000000000000000020000000000000000000000000000000000000000000000000000800000000000080000000000000000000000000000000000000080000000000000001000000200800002000000000000000040000000000000000000000400000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x193",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xfbe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514",
+ "transactions": [
+ "0xf87a8201430883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0097f470d08b374cc1ea0e0ecfb841f22e6f105c4989a6a41f23619320011f4dba06c843174399416f4a98ee5b5170a4330fbc487cc1bdc4e67f8eb3ca279fa8415"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np404",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96e966680b69cd6f8f3c95b0bfcaa337959db055f2b4329813dd02f9e5350742",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x194",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xfc8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da",
+ "transactions": [
+ "0xf865820144088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09fd0702bca1c10269dcf83862a9f07981858a8a1579f3ed68642fdc8b77478cda027b1f49755229583c844b747c040251c2671dcfe83fa26df37d4bbfb54635864"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np405",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7fa007461e28a3bd63c35eb625b4c122197ed1d63a00b0a0959652cb745c034d",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x195",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xfd2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820145010882520894360671abc40afd33ae0091e87e589fc320bf9e3d0180c080a09b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87a02c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np406",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3d03d9ffcd17834d8b99988eb8c1c9f36b8e627f50e2d850a6538d7610ba8457",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x196",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xfdc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x41",
+ "validatorIndex": "0x5",
+ "address": "0x6510225e743d73828aa4f73a3133818490bd8820",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np407",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xeb5feebaa9bd10619704d66efc97f95338c3e02dcebc2710be462faa47ddfc63",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x197",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xfe6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996",
+ "transactions": [
+ "0xf88382014608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e767d5dbf82d8857bccd947a04354b0023b0e283098f75e4d7d79348c24dca95a00a4d04094359f0817637570cf1ed12dcd2614da2e845751734d67175839a3903"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np408",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaadc011ce89c8dd628f56494b7f19d8cf66c1555b3cb6b38fd6e31c908e83804",
+ "receiptsRoot": "0x0c78f3779ab455eed4ce5e60071fff80a3d289a33fd656e17017d53978fada5d",
+ "logsBloom": "0x00000000000000020000000040000000000080010000000000000000000000010000000000000000000000000000000000000000000000000000000004000000000000000000000000000001000000000000008001000000000000000000000000000000000000001000000000002000000000000000000000000000002000000000000000000000000000000810001000000004000000000000000000000000000000000040008000200000000000400000000000000000000800000000001000000000000000000000040100000000000000001000000000000000108000000000000000020000800000002000000100000000000000002000000000004000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x198",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xff0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606",
+ "transactions": [
+ "0xf87a8201470883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a00eab4059563c228f12cd79cdc77c5594af5bb5f9778dab439aead79a99c7da9aa010476536728e9bf977ad4c2cc25fb7d5587869148789e9fd6bf40d65b9e94bbb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np409",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0ed00985c27ccb9453093f70f7cae8594259e64c8962ee22121019210fe01824",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x199",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xffa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259",
+ "transactions": [
+ "0xf865820148088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0310416be8b0e49ec34116f9c8eb4dd4d4dc6e39e5c97ccb94ac96e8cd21a7333a029b7a950def860ab8bfd4e49e5f34bc731344ab60770ea27f656e64e6b2f90de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np410",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7ff6b18a2c62836e16cad9956e08422a430c268cda51f219422b628491066c6e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1004",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78",
+ "transactions": [
+ "0xf8688201490882520894579ab019e6b461188300c7fb202448d34669e5ff01808718e5bb3abd10a0a0de600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dca047d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np411",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x95d1e2783fcf975ce0a79a05166ad33628065812d76f1f92f88d8f77f5a49e88",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x100e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x42",
+ "validatorIndex": "0x5",
+ "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np412",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa1e185a2970fcd9903cadff06453ace3bff731a5295334d332c3fafd1d50033a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1018",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf",
+ "transactions": [
+ "0xf88382014a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06222a14090e09278dc92b9002ee33b54e5bbbecd9afe56fa18d00dfe761ce8a1a06e8ec220dc8219ae16f46f3a4696fc8b4046fd33fa41efb473222fc058d65ed4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np413",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19a70ab3d8102a74b87887d95a29fe82ce4d4ab36fe3f57f336ded8bd0a7b3d6",
+ "receiptsRoot": "0x2ac314ac40ad6f04e3ec1fc2b315d4ce6eb64537ae9bf3fad670a0a1df1e5e3a",
+ "logsBloom": "0x00000001008000000040000000000000000000000000000000000000000002000000000000000000000000200000000000001000000000002000000000000000001008000000002000000000000000000000000000000000000000000000000000000080000000000000008000080000002100000000000000000200000000000100000000000002040000000000000000000000000000000000200003000000000000004000000000000000000000020000000000000000000000000000000000040000000002000000002200000000000000000000000000000001000000004000000000000000000000000000000200000000100000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1022",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581",
+ "transactions": [
+ "0xf87a82014b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a07af33005afb5f1b38c17ed2bb2b83a0c1d0d6ecd30ab4e32091582d5a3eceb28a008bfc076226d8ebf0a2c86c5ea5f65ea1f1d0cb7b7036b2049444c2fcfb55031"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np414",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0e4a2aebaaa31e943227335fd579582b6ed68abaa2706294b038ccb00ceae64f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x102c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd",
+ "transactions": [
+ "0xf86582014c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa05e26cfc612b47c55ae5a521eca26d4adbeaefe893bf1b0226cd121cbd7cdb45aa00be4c1040e89e1db4b10b4f36b38ef682de4f3308fd65d4f39346ffcf016cfdb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np415",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc149cc44783e5dc5c6be9d4facfc2e9d3d31dff27f8495ea3fc2acfc22310516",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1036",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82014d01088252089488654f0e7be1751967bba901ed70257a3cb799400180c001a0a79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0a0750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np416",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x39d41e6a842119b876ef50fcce4e677b2760950f191f0b17ac11bb61f5d271b0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1040",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x43",
+ "validatorIndex": "0x5",
+ "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np417",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6f8f7979fade5692d7fd5e0f6253e0e3082614421af4bcfbd63c12f2df06876f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x104a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631",
+ "transactions": [
+ "0xf88382014e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fea6631902fceb5662ca53076387bbbb0e0fd9bcac1df121172fd29bd6700434a0632755563256841b198d853ee1861224df35abe91c6d15ca60cb3f660ce05e2d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np418",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x26b3aa514e4bfed98a760b1cc6d5c7c855232ecac4f00826049369385376458b",
+ "receiptsRoot": "0xa3ea729352d4252acd6b48dcc940d3acfe0d657ca5d3091eda1ae882c7c14776",
+ "logsBloom": "0x00000080200000000000000000030000000000000000000008000000000000002000000400000400000000000080802000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000800000000000002000000080000000000000000000000000010000000800000000000000000000000000000200000000000000000080000000000000001000000000000000000000004000080000100100000000000000000200000000000040040000000000000000000040000000000100010080000000000000000000000000010000000000000000000000000000000000000000000000000040000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1054",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5",
+ "transactions": [
+ "0xf87a82014f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa08ded8700920cf761c49ef0831076f10597be8fe624b891585941b1a1d145a18fa05640b1e1c59257bc6b6352be6bb6a7862a541b3fca52da28912b08b8072b57e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np419",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x730477c9b8be2e32598ff45ddf03837963e5d2fcd5c8c07d23b47b385c22d4b7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x105e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211",
+ "transactions": [
+ "0xf865820150088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bb5b1c9e4a9e86b6381ce83f476e3efb45b847315ec3e27e1536539ba2290f42a07eee4b7b9b0d0dc1b873baf519a668f4605ccbb82ad619acb74598535a35bdd1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np420",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xef5088187720800d3dec63e4e25560c839cad852b7a795fd9e9876ee2a02b16a",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1068",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b",
+ "transactions": [
+ "0xf868820151088252089447e642c9a2f80499964cfda089e0b1f52ed0f57d01808718e5bb3abd109fa0c37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618a0190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np421",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8fa327b5c3e6a5036585a3b751910d613c3d2b6b56b0a5c1da7727ce50d4cb57",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1072",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x44",
+ "validatorIndex": "0x5",
+ "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np422",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5eef4d5746f0409111e198bb292fd06bf9ac9a14dc734ca636005246e713e5c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x107c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c",
+ "transactions": [
+ "0xf88382015208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0435a46c3720f21ff83b01b3d6e88f602e45dee024e69f7df083e47ee400fa063a020b2e545bea301a0322157c61d6f8bdee62066305c627c1c10fb9eb1fbdf0fed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np423",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5486d8d4c4159eb6389774b47a76d5e347e3b31ecf92c08eda9e261e3106f0cc",
+ "receiptsRoot": "0xc0c07d0984b850e6ccc2e081d26ec135c42d526e9bb51a6c1987784d659c07d5",
+ "logsBloom": "0x00000000000000000000000000000200000000000020000000400000000000000000000000000000000000100000000000000000000400000000000000200010000000000a00000008000000000200000000000000000200000000000000000000000000000000000000000000000001000000000000000000000000000000000000000806000000000000000048000000000000002000000040000500001000000002000000000000000000000000000000000000000000000000000000000000000000000000000000800000000800002008000000000000000000000000000000020000100010000000000000000000000000000000000000000010000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1086",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212",
+ "transactions": [
+ "0xf87a8201530883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015ae0fac40a467ff5ad10fe01c838c564f0d30707c8b02be656345842959fedda07a3d9842f721d8cb4494a2df6ff689c4c19e44c8c81f013d1f969624d49850b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np424",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9339a9c149937412b8c9d01a85c7af270578af9eebb80ad2cf208764c40e608",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1090",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91",
+ "transactions": [
+ "0xf865820154088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0c14791fa1c6907f6279226a31c5f287c93702ba72f19fb9999b93b8ad612b36fa0371a0819796295976ab02fcafbe818a711cf6485a21d038dcb72b5000f04d63d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np425",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac3cc175fd0ba02252342155b4d9dd7fb790eb49b667058912b43f5bd6e939d5",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x109a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820155010882520894d854d6dd2b74dc45c9b883677584c3ac7854e01a0180c080a07a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09a075f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np426",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe677d652ba3a8822155791a1d1491ee57497ebfa49e3e38c909752dd8067a9e8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1aa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x10a4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x45",
+ "validatorIndex": "0x5",
+ "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np427",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x08414161950ff53f6f053f2886c473a22eb595a0052de01fd24c7af1bc27a5ac",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ab",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x10ae",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec",
+ "transactions": [
+ "0xf88382015608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f6b9a47dcc55d9130085e0dfd615fee0acea46517280eea07dff8ee6afd40e3a01fc33c02a467db6d30ccf56ad8b5bb32fd49ad9a7866db580e7a581987518921"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np428",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5afe7e66edc543cc377a33069ba58d5788801f1ef0f370d69ff71db5f63b6b88",
+ "receiptsRoot": "0xb278e6670351b21cd1c267f24972d7868327ae82ef7a3b377af968b4c6659925",
+ "logsBloom": "0xc0000000000000000020000000000000000000001000000001000000000020000000000000000004000008000000000000000000000000000000000000000000000000001000000000000000800010000000000000000001000000000000000000000000008000000000000000000201000001800000000000000000000000000000000001000840080000000000040000100000000000000000000000000000000000000000000000000000000800000000000000000000000000020000000000002000000000000000000000000040000000000000001000000400000000010000000000000000008000000000000000000000000000100000020000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ac",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x10b8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34",
+ "transactions": [
+ "0xf87a8201570883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cbb3f84663bf7369864941fe566b1beb8d5db0095cbd49ebfdee89c164031e6a0461b62f4b01d15206e95e6c7bfe9364456d8b7edd446d1b488a2688c47b83775"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np429",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf1c25b007a4c84577aa49389214e8b8b63f81cb20b61095db784cd8e781fbdcc",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ad",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x10c2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e",
+ "transactions": [
+ "0xf865820158088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a285aa615fe480c778997ca57059b8ddec5cee0e5a94ec05cd028a03d04aadaba07549f0c6ded9fe03eb40b413803b8f02d9dc51591e29977d12a204518648008e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np430",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x401f1feec84dc7c894bb9f03dd52b5af121262ab2f6bd29e6de4e96c1ed67870",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ae",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x10cc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d",
+ "transactions": [
+ "0xf8688201590882520894c305dd6cfc073cfe5e194fc817536c419410a27d01808718e5bb3abd109fa0163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810a04ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np431",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc97f5e63e102992e2a849afad97481ea818d213707de515acd9c2bc246cdf65f",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1af",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x10d6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x46",
+ "validatorIndex": "0x5",
+ "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np432",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9c177f669a297c904a6a6ad51765a5916a0e0a3d9858b289e70bf054b370d685",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x10e0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586",
+ "transactions": [
+ "0xf88382015a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa078d6fdbc4224106e1f59483aff597485ed0eebf922317913522a0693727b5ee8a035876b3170b9a88dc391f83dcac8088aeb65233613c74d8f50f1d1d3b1ce842f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np433",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x98d101f68f7aa5bb170cfdd60281d7a5c3ae335ab03c0f87bdb5e72cc022d55f",
+ "receiptsRoot": "0x1919995eb19582a49f7b79b55e7ec75fae399916006f29e4177543d99cc2a5e3",
+ "logsBloom": "0x00000000000040000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000080000040004000001000000008000000000000000000000000000000000000000000000000000000000800000000000000080000001000000000000080000000000400020000400000000000000000000000000000000000000000000001000000000000000000000000000000000000000000012000400000000000002000000000000000200000000100000000000000000000000000000000000000000000000000000000004004000000000000002000000000000002010000004000014000000000000080810000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x10ea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a",
+ "transactions": [
+ "0xf87a82015b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09fb0d3ddf1fce9562d227b3cd6c35ac2e89f39141823d94cda0e6efb4519c715a06925af0950104623efa7954872196fe6d539eb269263a17db3740652382d100f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np434",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7d06044c1009a2320b83bdfe22ffe7b8ffa6fa1f65d5e42f7c1588417a8ff421",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x10f4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08",
+ "transactions": [
+ "0xf86582015c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0aa24c6fb2c99f1ce21f7ffd84e87fb6f81ff76cebe06fb5c0871294a353210dfa0350602877ed48896e8b4124b35c0c47da66c17fc0d553d9248ca1de942114306"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np435",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x03d23380eb6a02b52fcfeb82c0fefd180c014e72a7f48f2627237e7bda6d5610",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x10fe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82015d0108825208942143e52a9d8ad4c55c8fdda755f4889e3e3e77210180c001a0673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88a017f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np436",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf8829f712e0ea692e266ae3c78400816c5f5bc1d75a3bff3816f7fef71b2044c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1108",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x47",
+ "validatorIndex": "0x5",
+ "address": "0x5123198d8a827fe0c788c409e7d2068afde64339",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np437",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc66ecc1bdb4fa4b85c0b383d4db20fdaa2cba32973260dc444abb43e8536e93a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1112",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac",
+ "transactions": [
+ "0xf88382015e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0179370023b242bccf25d4899c2f29936353b5f1c37a8f7c665e55b75f80bf297a018a66d1d2ef7072f7fc54af07d15edc14ecf5a71f510be740c090f0815178ff2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np438",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9b50e298c6a4bbd23a659ab24a3a7426b1087497561c39de2f1bf27da019b83",
+ "receiptsRoot": "0x8f45041560ebf83ec428723c6d69db271346e4c5a1b234b56efe318d549187cb",
+ "logsBloom": "0x00000000000400400000000000041000000000000004000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000080000000000000000000000010000000040000000004000004800000000000000400000000020000400000000000000000008000020400000000000000000000000000000000000000000000000000000000000000000000000000000000000800002000000001000000000000800002000000100000000000000000000000000000000004000009000000000008000000080000000000000000000000000000000900",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x111c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86",
+ "transactions": [
+ "0xf87a82015f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0354b9d4a470abdae9da30183321b96b5fd09bc96c1ebd3137b3c6350c21e8de2a026877262b14edc851e17cba052b022dd1038fd51ef65ecbaff09dd07186f035a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np439",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xad6a72de336a98aec47ed431bf7d39d537741125313255629633cba91b0097bd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1126",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3",
+ "transactions": [
+ "0xf865820160088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa09c6b3542e181028aad33517584cd16e92836f975955abdcbf1205b6250c921d4a040816d88e011c2d3073502523867b94987fa0781793a7857ff2453ec2d121444"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np440",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x863de67ea016127a436ee6670f8642bd5ab997ce75361c3cce667abbe90b7283",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1130",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192",
+ "transactions": [
+ "0xf86882016108825208940fe037febcc3adf9185b4e2ad4ea43c125f0504901808718e5bb3abd10a0a0654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892a070505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np441",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x66989995258d8db8bd3b8eac83c7762c50323b8f21f1aaddf3ad0208afc6318d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x113a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x48",
+ "validatorIndex": "0x5",
+ "address": "0xd39b94587711196640659ec81855bcf397e419ff",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np442",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf37b2d059d8764938039410fc2581f4793fb4f9c66abf4f8a32276dd60334f4d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ba",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1144",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e",
+ "transactions": [
+ "0xf88382016208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf7859d7e53ab582f4189f50f06832f2fa9763498350b739d7a677b34df97861a03ab21050f73bda7c737cef08e6a77edc9766aa0ef14dfdfc22fbcfdb6771825e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np443",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x23eacf2b963df64726e41314251669bf12f3925de3933e0b713863d1a7a6fc6b",
+ "receiptsRoot": "0xc97de406788b669a824183dab763b8caa8988371aea1f18b96e6b1f9abdee729",
+ "logsBloom": "0x04000000200100000000002000000204000000000000000000000000000008000800000000000000000000000000000001000080000000400000000000000000000000000000000000000000000000000000400000100000000000004000040000000000000000001000000000000000080000000000000000200000000000000000000000000000000000008000000000000000000000000000040000000000000000040100000000000000000000000000000000010000080000000000000000001000002000000000000400000100000000000004000040020000000000000000000000000000000000000000000010000010000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x114e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96",
+ "transactions": [
+ "0xf87a8201630883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0332397d6a00a7d2a3453bf053c8d158774d82d6ea252c2d564bbd48f9e882418a01187aef824b2759cba8c1574666919b77889353a9905720170518b03b38cc71d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np444",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x71e7debe9374beede2414966d6eb2c2eadf548c293ba65821869bc274709badb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1158",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e",
+ "transactions": [
+ "0xf865820164088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b7296876d0713a392d440d71244cda1a3ecb09009a2f4d0ae5d26a398a8bee92a04dd844c3b7cbf88f10b080a3a0fd8a0e21e8d3041450c69786efe9ee7af18dcc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np445",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58a574089cbd9986bf63c3ee8e0e8d400e9b97b8d1280166f7505de051f4c661",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1162",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820165010882520894046dc70a4eba21473beb6d9460d880b8cfd666130180c080a09a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996ea0418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np446",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd0820c57ebb5be91343940d7197af10c1d95a23a1b99bc5fa1a77997849273c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1be",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x116c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x49",
+ "validatorIndex": "0x5",
+ "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np447",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbc2acbe23d81c5bec8c73c20cfbb12be681cc92fa399ed4a44e7a91fb433c577",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1176",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f",
+ "transactions": [
+ "0xf88382016608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0daffe9dd6ca6d33e1a44ce5725c7e795639c4bd4a36cfb18d520c9fc892b7ca5a01286dcff57cb583238854ca89346c969387d982ca7e14cbd82413855fdda282a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np448",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x95fea999be7fc8cfa0e1c8a9a10dc33d073417bf87ff698edab332c6e18ecc60",
+ "receiptsRoot": "0xcf29f818a1be0922fc0576d2500603f4e9ab8a9e251986d891170f993f0c8f0a",
+ "logsBloom": "0x00000000000000000000000004010001000020000000000000040000000000000000000000000000000000000001000000000080001000000000000000000400000000000800000000000000000000000000400004000000000000008000000000000000000000000000000000000000000010000000000000000040000008000000000000000000000000000000000020000004020000000000000000000002000208200000000000080000000000000000000000000000000080000020000000000001200000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000010018000100000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1180",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa",
+ "transactions": [
+ "0xf87a8201670883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0745918999757459ef7ab7145b734444d0437fa7b3939a6ca2a07652a727d1ef9a0074b0898accddb3ac54941b1fce130c31edd3d838dfefd506668cd989f4c5389"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np449",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa4269875f0bd6dc1360830e3e07eae0956700e8c3aa69cd61b423abf51bfce54",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x118a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30",
+ "transactions": [
+ "0xf865820168088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa01f0e57c3b6f3908a7afb46717ef32caf9b73c4a4b2f48b09e0fcbea02ae716e1a017c79cab83300efab682d0c0438b23b49136a17e22560e75d32014c5951b4fd4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np450",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd315f1048882fde9bc00a0bae351ab3229cec00efa7ef4b61fd5c1be40619f81",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1194",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08",
+ "transactions": [
+ "0xf8688201690882520894104eb07eb9517a895828ab01a3595d3b94c766d501808718e5bb3abd10a0a0597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0aa01f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np451",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3222feed7d40d321811eb16ac78aaa0561580b176e0605bfecc30427a7702996",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x119e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4a",
+ "validatorIndex": "0x5",
+ "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np452",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96bcc6f26c5f94c33c57d1614edd2b385e36d9972250c79758eeaeb09927c0a8",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x11a8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9",
+ "transactions": [
+ "0xf88382016a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03fc929c6e9476221ddd5f2f5093981cc13f4b8206ee3454720f06c0bd5c95caba038f23a2c21ba59155127a15502ddd731f30d6f94c6aafde8e73fbe39237766a2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np453",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x168c847144cfea8b88e6ec4f673ebddbf18331bde8002e044b1d1df7408edf04",
+ "receiptsRoot": "0x4ff26b781abcaf6d8a14f4f5283feeee87038dbcb46b9987d6042a01b1b07f9a",
+ "logsBloom": "0x00000000000400000000000000800000000000002000008000200000020000000000000000000000000040000000000000000000000000000000000000800000000000000020000000000000000000000000000000000000400000000000000000000000000000000000000000800400000000000000000000000400020000000000000000800000000010000000000000004000000000000000800000000000000000001000000000000000800000000000000004010000000000000004000000000000000000000000008000000000000000000000000004000020010000000008000000000000000000000000000000100100000010000020000004000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x11b2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d",
+ "transactions": [
+ "0xf87a82016b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07061a8a3f917f765ec8aef5e4ad237d377c0131f63f31da7bdc6af9942a1bc4aa051bf3e7c6676f2fbde507834995f4e269113adf35b98bc71cd22d9c168692f5c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np454",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e75fe29c17414bea5febf41c577c117b57c1a731aa7a18b6c5d2ba9e3bc27dd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x11bc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c",
+ "transactions": [
+ "0xf86582016c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ec3fe55b96a9d14e22fc0a8aa5991138ba954245754c0e0dda2b5b7dbb6711caa0296a6b87da18224fac7c922e2a7f0ec41330a6f510934a1e0e3c6a65dd72dfcb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np455",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdf26695268f674fc809ad21c323bcab53727af440302b923eec2d46ee3cd7aa3",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x11c6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82016d01088252089446b61db0aac95a332cecadad86e52531e578cf1f0180c080a0774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008ba06f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np456",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x358b2d72362d209f8c7131a484e49caff1dda8f550fe6103be80ac369cfe49fc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x11d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4b",
+ "validatorIndex": "0x5",
+ "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np457",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2dd7146f049ba679aae26c42d1da7f6660ea964a7b227509e5296a9d0170e93e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x11da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4",
+ "transactions": [
+ "0xf88382016e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa038214a2cc756a0ffe043200d5e12183223f81912c0156df732c3b1d85bc2a237a0744a52bf9fca64223bc279e589d21b9fda190325bf3b576f41a792ccbec5bc08"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np458",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x62b1bdf3b4a63f480b24af9f3b55dc6ad6e52bb81caa13b286960694b3b600b0",
+ "receiptsRoot": "0x25a0fc424c07569fb4229958de04f1d6497b3d8b6a78757f42963f95c354e2b1",
+ "logsBloom": "0x10001020000000000000000000000000000000000000000100000100000000000000000000000000000000800000000000000000000000000000000040000000000000000000000000000000020000080000000000000000400000000000000000001400000000010006000000000000000000800200800000000000000000000000000000002000000000000000000080000000000000000000000001000000000000000000000000800000000000000000000000000000000000000000000000080000000008004000000080000000000000000000000000000000000000000200000000020000000000000000400080000008004000000400000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ca",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x11e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c",
+ "transactions": [
+ "0xf87a82016f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa05e304ec406ec4c83644417e1e58b49757d3ac78da5c5280fbda19b1f149137daa035b73caa8da3b6ce0e5f1b014c127f93f7be595f104cd933b5ff07549fd1812b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np459",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5614ae860626ff1e044740a53f3cb5126f72002928c034aecbdfe4291ce73b91",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x11ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5",
+ "transactions": [
+ "0xf865820170088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05d0d172a5fb9787aa2ee5205e5986de935984adf6030d5668be0e31332f7b145a022c4c7a89391e8f4508095fc5c1ed16aa0c08da6790be108240dc64763d42dae"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np460",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x715b0d1e4306032fa54c79f84599828d98bc84ed9cdb52a407e58730b4c112db",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x11f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6",
+ "transactions": [
+ "0xf86882017108825208948a817bc42b2e2146dc4ca4dc686db0a4051d294401808718e5bb3abd10a0a0a755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1a067d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np461",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c6710fa12f6392a52eaa92d776fe1c24245dd52883ff2276547e65c34952eeb",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1202",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4c",
+ "validatorIndex": "0x5",
+ "address": "0x48701721ec0115f04bc7404058f6c0f386946e09",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np462",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c73a23f75ee594dacc63d24a5d5655a1ccbeead972dba58ad86787c44442c6c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ce",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x120c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61",
+ "transactions": [
+ "0xf88382017208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0567311948632a5f4d53e0491aa8e7f939a3e0da38be1db4b6c757422de3f8bf6a01134e092948e423c7f8867c02822c95f3ce21b6d4e8d3666e2cf47ca88ad7499"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np463",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb6a995ce6f848e4f2f2ad8ced5491859a5d0a3b6767108f3ce5cfcb33303349f",
+ "receiptsRoot": "0x5bb341cd099f8898164b032e64db73752f528a10e8d9c60c9b4fff08af32dcf5",
+ "logsBloom": "0x000002040000000000000000000000000000000000000000200000000000000000000000000000000000000000000300000000000000000000010020000000080000000000000000000000000000000000000000000200000000000000201000000000000000080000000000000000000000000000000040100000000010000080100000002000000000000000004000000008a0000000100000000000400000000000000000200000000000200400000000000000000000000000000000000000000000000000200000000000000002000000000000000000000000000000000000000000000000030000000000000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1216",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d",
+ "transactions": [
+ "0xf87a8201730883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06092eab6a3d9e41841ad4b9c97154ac35269c852606da6dd04940a1a055fa979a052a6e3e769e27310acdef840cb1182f4a2b6b08583b01cb8325c98253feaf7aa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np464",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf54cc52e78b0ea88b082230970d262fc78070bff347c000f60c53400d111a59c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1220",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e",
+ "transactions": [
+ "0xf865820174088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0342c58642563f78afdb5cf7b9fbc935268a8fd81a5bd7997c33f61cdff8fb9c2a07466870d997603b5dd7755f151b76f056d4948ae82372b05babc01b9addaad19"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np465",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5b583ecaeffb409a488709df2c592c932e93a9b954bb5b62c36739324ae7d89c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x122a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82017501088252089423e6931c964e77b02506b08ebf115bad0e1eca660180c080a06263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242a02b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np466",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdaf72de0a7092d2a2a6d31336c138ab45852ca65398578fbc435b3c591fa7c3a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1234",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4d",
+ "validatorIndex": "0x5",
+ "address": "0x706be462488699e89b722822dcec9822ad7d05a7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np467",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb9f6529424870d0fbfe7d70438762f3ccf9d2f212d3e42c837f6e9218d72451a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x123e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810",
+ "transactions": [
+ "0xf88382017608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e42b1ec38a455f867d421d170e634c86f8a84a2cb00ec5024f343667042f303ea067797c75de08e6eafd819d4c408324fba318e16b378b7dedbc0708056aebb696"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np468",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3017b68d781fb29ccbca4c6ff597a9e18d6cee4f02974dbb32f04b5a7f519271",
+ "receiptsRoot": "0x00fbb0bcdb236cd79dbbefe84d42f31ee3274cc5e9116ffb0d70301b983dbd52",
+ "logsBloom": "0x00000000010008200000000000000000200400000000000000000000022000000000000000000000000000000000000000000000000800000000000000000000000000200080000002000000000000000000000000008000000000000000000000000800080000000004004000000000000000001000000000000000000000000010000000000200000002000000000000010000000000000004000000000000000000000400000000000000000000000040000000000000000000000080000000000200000000000000000000000108000000000000000000000020010000000000000000000000000000000000000000000000000000000040000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1248",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9",
+ "transactions": [
+ "0xf87a8201770883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa01975b5adb5e05e7dbaf63d31d34e5dfb802c4ca28127176811ada2b0a9411be6a02b9cd65ba817631163e95275ec2bd5319edeef4f74eb6efb32150a523282db16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xefdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np469",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7da79133a491b6c2566dc329ed006ee0010fe59b515fbce5589eda0f31dd091b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1252",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832",
+ "transactions": [
+ "0xf865820178088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02a73665ddc16b8e231ef04b5f0ad8afa56248db6f43222848032c72e97a807b8a00a17dda1a1d0ba616354fda9e86c836bcb002c7e54153be4cc95776446c6b2a5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np470",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcbeab9491879fdd48e387106f31e983546cff3f4795ff5190722d2ac1f3792b6",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x125c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0",
+ "transactions": [
+ "0xf8688201790882520894878dedd9474cfa24d91bccc8b771e180cf01ac4001808718e5bb3abd109fa0515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367a023756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np471",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x60452d4fa157207a12986fb9c810855fe19a2492ad046335ec9b4fe41e48de19",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1266",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4e",
+ "validatorIndex": "0x5",
+ "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np472",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0b580cdca4b5a562a85801f2e45bd99e764124b9715915fd4bfc6f6eb483ef96",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1270",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df",
+ "transactions": [
+ "0xf88382017a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05c8cad8eec0edc7394b3bace08088ee19b7eacb754b0a5695fc52a0cd17c19f6a0033d27e9eeb87fa5ae4868a14d0b66d941f0ffa3a3781e60cbb751bab7b507da"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np473",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd08b438590148463c602be8f8899fd6c2cb42972fe2df0e71cb42ebefea3f404",
+ "receiptsRoot": "0x307ca5ba4dfd34e9f362cea8e1f54ff58f9318a35cf7e1ae24823d41572d7742",
+ "logsBloom": "0x00000000000000000000000000000000800000000000000000008000000000000000000000040000000000000000100000000000000000000000000000000001000000000000000000000400000000000000000000000000300000000001000000002040000000000000008000000000000000000000000000000000000100000010000000000000000401000000000000000000000000000000000000000080000000000058400000000400000800000000000000000000000000000000000001000000000000000000000000004000000000000100100000000000000000000000000000000200400000000000100000000000002000040000000000100000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x127a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1",
+ "transactions": [
+ "0xf87a82017b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cfb2ecb740895c1bdd352c502898651d83d35cb17ec4a0b30b04fe190a05758a02606cabbaa5b1d57ff9da73837cff8cbd03f242b83880f8cf3ba6f0ee907d538"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np474",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d86e3351111e6c2d4eafc36553273c03636a22fae54a9e076be2e7cb0cdf9d7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1da",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1284",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3",
+ "transactions": [
+ "0xf86582017c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a044380da66c7033fceaa15191e7549bd08fed4c16f96cf1282b2f39bccaad1ff0a00d036ed4649f8300b82a534b03a19b4547784997b61328ba41dd7fa5380de99b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np475",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e2eff0a0a0cfaa9726ffd557089d4a85855fabe4b81334326bd400289f5ed12",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1db",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x128e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82017d01088252089445dcb3e20af2d8ba583d774404ee8fedcd97672b0180c001a0d3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4a0368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np476",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3de8e5ff6961615b029591cbe9ea51723c809d965421da4f3f8ae26ffe59d69d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1dc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1298",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4f",
+ "validatorIndex": "0x5",
+ "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np477",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6eb0d2ff3e3dd2cdaad61b121b06afcf7863f34152ecbdf8b8773604630a56b3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1dd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x12a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257",
+ "transactions": [
+ "0xf88382017e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0939d9f6f260f24b45073aeabe00660f617f1dbfcf522cd6c90ef189dfc9dbfa0a02dfd90c6f1a6822039b8fbd5bff435e939882da970ed1b58a4639eddcb79b23b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np478",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfadd61dbce8d90cae8144c1b2297209079517cb13f3a4e60a6c8f2ea7b4d3770",
+ "receiptsRoot": "0x3ec27c047700a74288e3ee48062fed9fbba71b1704febedea9f4e9e3a92faabf",
+ "logsBloom": "0x00100000000000000000000040004000000000000800008080000000000000100000000000000001000000000000000000000000000004000008000008200000002000004000000400000000000000000000000008000000000000000000004000000000000000000000000040000000800004000000000000400000000000000000001000000000000000000410010000000000000000000400000000020000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010080000000000000000100000000000800000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1de",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x12ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00",
+ "transactions": [
+ "0xf87a82017f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0dffee1543462b1d024b5d54728f2e3284d90d8fd24b94fd96bd027b4ca51e768a02ed5ddd2050f1b7bcbc123e31fb0536fbf1661a8f7541c7a10729e8a505cc080"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np479",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x931dde8f1566d5b88162261e5f8c8fede3f14bfab1c11934aae8f2a38aca7b36",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1df",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x12b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece",
+ "transactions": [
+ "0xf865820180088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c2e07d6867be2220a74a18404d2b9b9adb2f6b1764907aaec954f46e0b9fd18aa01504fbbb49a910d6469e64741d99ea5031c14d4721e488998ef2f594022f34e2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xaf5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np480",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x452e515470ad9f96543d5a469c85e77c4f675f70a56662537491b01528898b99",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x12c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9",
+ "transactions": [
+ "0xf868820181088252089450996999ff63a9a1a07da880af8f8c745a7fe72c01808718e5bb3abd109fa0f06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6aa07fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np481",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa424a562451b0728dc1451b83451fb65f9cad240a6e12ae45314a3c0fc49c4bd",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x12ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x50",
+ "validatorIndex": "0x5",
+ "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np482",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5a1ad989a90bb48e30208fafcd5131d4dec171928eb27a8ab446df6086df0f94",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x12d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1",
+ "transactions": [
+ "0xf88382018208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a085873eb64b12c743e5652beb56056bd656368a87247a72b159667d4755d7a714a0134397c5062d25029e41def2275efe8c56e466e3a1547d3525533e29641d203f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np483",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x54928b5673094b4ce9833ecf8c1490381f0317ac2e9d51f47673e386b82ae93d",
+ "receiptsRoot": "0xeda5fd4b20fab5a0732205bfe235b5b212cfa5eb525752ae8b9bb0ca224262ec",
+ "logsBloom": "0x04000000000420002000000000000000020000000000000000000000000000000000000000000000000000100000000040000102000000000000000080000000008000000000000000000000900000000000000000000000040000000000000000000000000000000000100000100000000000001000010000000000000000010000000000000001000040000000000000000000000000000100000000000000000000000020010000000008000000000002000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000080000000400000000000010000000000000000000000000000000002020000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x12de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91",
+ "transactions": [
+ "0xf87a8201830883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a05c87beb281558e43744b39a1d0b62e75dfb5ea245fd2d66c657ff053fa5c45e1a077a1c629133272d7fef83436c8f67f327fc77bedea95009b3d569a5f03485b50"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np484",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf92302c8ac6987ab39ddc9a7413f552337da61d611a086900a5e47b9b3c1422f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x12e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958",
+ "transactions": [
+ "0xf865820184088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ef66b5859d5e5be7e02ce0b7d103b957ceba18d69047aec94746e87945b7230ba071c5785cce709e44dd94db5684b4e552e343a44862fba233c49a3fa99b0d63f9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np485",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x89822c6bc267d77690ae905ebc8dbe9426f9a83764224d4bc9624104881db28e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x12f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820185010882520894913f841dfc8703ae76a4e1b8b84cd67aab15f17a0180c080a0d4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8a064c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np486",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe88ebfc2a7990356801a2e5a308418fa8fe4445548fafe8227f4382f64ad8597",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x12fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x51",
+ "validatorIndex": "0x5",
+ "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np487",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb852ee14e385a383f894d49c4dabd2d0704216e924283102b9b281ae5306a291",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1306",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6",
+ "transactions": [
+ "0xf88382018608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0ddc578e5c190613c2dc0ce34585e98c512fc9b4ae877b0b3f9b85e01a36b90b5a044c7152f99374ce61bb3b9ebb9ec9e5c4f623faa9b8972cf80f891fd45be9bbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np488",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa3f2cdabc9ec81196b1930e223115ab39e3aa82a3267c2eab58dfcd4ac28879d",
+ "receiptsRoot": "0xa98965822a3cbebe261b9e53038a23e30a7a9ea1878b91ee19c2b9ae55907433",
+ "logsBloom": "0x0000000000000000000000000000000c000000000000000000000000000000000000000000002000000000800000000008000000000000000000000000000000000000000000200200000000002004000000000000000000000000000000000000000000000000000000020000040000000000080000000000004000000000000000000000000000000000000000100000000200000000000000200000000800040000000000000000000000441000000000000000000000000000000000004020400000000000000000000800000000000000002000000000040000000000000000000000000000000000000000000100000000000000400100000200000010",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1310",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d",
+ "transactions": [
+ "0xf87a8201870883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09d84bd49c461dee138a01ba1116ba5a0866c4d398db99b3b6e8ec5119ddaf31da046d87610c10b340e616174c09a5addfb8ef7f1b64dcadf4edd14af37ec74a55c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np489",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x39ebb75595ae4b664d792fdf4b702a8a4cec3fb1fa62debd297075d3543e05af",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x131a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db",
+ "transactions": [
+ "0xf865820188088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a06ffd1874ec840566ae82b8a15038ee44b5241705bdb421b459c17100d1300d1aa0121f314d9f41658c831f52b82d4a13b333413d68809cea260e790de9283a434b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np490",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa3d5920be7fa102b7b35c191800c65c8b8806bd7c8c04cdc0342a3d28aeafa3c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ea",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1324",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb",
+ "transactions": [
+ "0xf8688201890882520894b47f70b774d780c3ec5ac411f2f9198293b9df7a01808718e5bb3abd10a0a0d33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5ca0667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np491",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf1034fb8a7585c73d7df19cae6b0581d6836278bd57d05fa19f18c6501eace46",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1eb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x132e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x52",
+ "validatorIndex": "0x5",
+ "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np492",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9b830dad01831671e183f743996cc400135e0b324f1270468af08b37e83b8b17",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ec",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1338",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92",
+ "transactions": [
+ "0xf88382018a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e94663b4e19d1c2f86adde879e4cb965b7eda513a542ba26136b7010aae11681a03e7d58f3bef3bba01e70b75c70bc0d070f95bba8994c9f12705f2a5281160f47"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np493",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc616c572be45daa3d7eae2481876e5d8f753631f976d4da110a6ad29bdfad30f",
+ "receiptsRoot": "0x78902fbbd0a8ab65f6b731f1145a5f6f467f9fdae375707236cff65e050bbfeb",
+ "logsBloom": "0x00000000002000000000080000000000800000000000000000800000000100000000000000000000000000000000000000000000000004000000000010000000000040000000000010000000000400000000000000000000000000080000000000020000000000000000000000000000000000000000000010000000000000000000000000008000000000000000000000000000000000400000000001000040000000000000000000000000000000000000000040000000040000000880000000008020000000800000008000000000000040020180000000000000000000400800000000000000000000000080000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ed",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1342",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4",
+ "transactions": [
+ "0xf87a82018b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0fbd0141af6d135ce0949d33ba4beba57e9b7f388c37e9725b762cb61e8db17dea05ecd43ff335efc34b06551202c4223fc39e1c842d4edfad8e46f19bc7a93f57f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np494",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e626fcfe3b1ca7a31dc26a08fbc503c7a85876a64a22a270ec99ef534566c45",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ee",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x134c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8",
+ "transactions": [
+ "0xf86582018c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05a02d5d03439ebbdf2c3b2d98305dda7adbed1ce5549c474b4b9e4f7200d4beaa016d123a1de79c4a654c1d1ab2169ee672c66922fa036e951c60fec9fe4643ee9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np495",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9d90c0fd0677204966d6fdbcafcfacc7fe93a465748d2ce8afbc76b6d9b9bbe1",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ef",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1356",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82018d0108825208946e3d512a9328fa42c7ca1e20064071f88958ed930180c080a0990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3da05d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np496",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32f6d8bc2270e39de3a25c3d8d7b31595eef7d3eb5122eece96edf18a7b8290f",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1360",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x53",
+ "validatorIndex": "0x5",
+ "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np497",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e1202b318372f0cacbc989e0aa420c4280dcb8ecd7c3bb05c645bf9fb27d54e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x136a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5",
+ "transactions": [
+ "0xf88382018e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0d9866a4e71a4efbccc717617f5c712557608513ce8b49f6e24fc06e0d717b7b6a056d3c051f6dbe09a1c94e23499ba8014f74e123caa3252068ee67e8f25e1e323"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np498",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd04a20f359c38d0cb7a31e5e7b002251c15e0242b864964ddbe9642d1c8f7e30",
+ "receiptsRoot": "0xe40714733f96bc282c17b688a91dfb6d070114fc7bc3f095887afa3567af588c",
+ "logsBloom": "0x00400000000001400400000000000000020000000000000000000000400000000000000000400000000000000000000000040100000000800000000000000000000000000000010000000000000000080000000000000000008100000000000000000000000000000000000000200000300000008000000000000010002000000000000000008000000000000000000000000000000000000000100000000000000000000000000000000004000000000000100001000000480000000000000000000000000000000000000000000000000000440000000000000000000010000000000100000000000000000000000000000000000000000000000000800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1374",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d",
+ "transactions": [
+ "0xf87a82018f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dd12539d461aa41247581166cecdf2eb60a75ac780929c9e6b982d9625aadc1fa06b813ce4e36c5147759f90672f6e239fab2851a63ac3b998ead89c0ead85589b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np499",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd38c27a1fad5fb839aad98a9c6719652d1714351f24d786b23bf23076b31ba6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x137e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "transactions": [
+ "0xf865820190088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a012969b1c46cb1b69a3fdf15b8bbccc1574572b79b38bf81803c91b0384309545a06d1c09143ad2bfeccbb04d63441058c83b60a5cbfdad87db36421dfcf008cd16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np500",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1388",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "transactions": [
+ "0xf868820191088252089415af6900147a8730b5ce3e1db6333f33f64ebb2c01808718e5bb3abd109fa085b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7a052e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/txinfo.json b/cmd/devp2p/internal/ethtest/testdata/txinfo.json
new file mode 100644
index 0000000000..8e1d917fb7
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/txinfo.json
@@ -0,0 +1,3018 @@
+{
+ "deploy-callenv": {
+ "contract": "0x9344b07175800259691961298ca11c824e65032d",
+ "block": "0x1"
+ },
+ "deploy-callme": {
+ "contract": "0x17e7eedce4ac02ef114a7ed9fe6e2f33feba1667",
+ "block": "0x2"
+ },
+ "randomcode": null,
+ "randomlogs": null,
+ "randomstorage": null,
+ "uncles": {
+ "11": {
+ "hashes": [
+ "0x900edfd7e6de8a4a4ae18d2e7df829de69427e06eb9a381c3fe1e3002a750d75"
+ ]
+ },
+ "16": {
+ "hashes": [
+ "0x750eda0129037fbbcfcbfd6362a60ffbbc53a3f14ba9259cf2ac7f02da2a827c"
+ ]
+ },
+ "21": {
+ "hashes": [
+ "0x763d1a545e23079b4796461f2146cd3b24cc45ceab6e932db010bd2736e45403"
+ ]
+ },
+ "26": {
+ "hashes": [
+ "0x98180f6103a7e303444de4e152e81539ad614d0cd755e0e655715ab676d11e32"
+ ]
+ },
+ "31": {
+ "hashes": [
+ "0x04a8c9b6d23b2ada25bff618036c08bf6428fb35b89bce694607fac697f470e3"
+ ]
+ },
+ "36": {
+ "hashes": [
+ "0x9225da0395e14243f1e626b330ea8fe6afde356e50e8448936a29e1c203d661d"
+ ]
+ },
+ "41": {
+ "hashes": [
+ "0x74a80b9b13a264aff16e9156de67474c916de966327e9e1666fc2027e1bf63ad"
+ ]
+ },
+ "46": {
+ "hashes": [
+ "0xcf2bddf3649c7af6e9c8592aa5fad693f39f46369749e1c7127848d4ae9ff1ec"
+ ]
+ },
+ "51": {
+ "hashes": [
+ "0xeb31c29a94de8cf2fc3d0b80023b716fb5d31cc24d695d606eef2389705ade45"
+ ]
+ },
+ "56": {
+ "hashes": [
+ "0xb3a6af7632306e2dbd56b3bbf0e77d7b5c199053f348c74ce938afae615cd4fe"
+ ]
+ },
+ "6": {
+ "hashes": [
+ "0x97186bc5df663e72934212ab5a7b4449f07f12f44b267e119817791fe0ed66c5"
+ ]
+ },
+ "61": {
+ "hashes": [
+ "0x3a2cf075f456fcf264293a32d41f72506ad8cf9697d6b6d8ab3d8258cdaa90bd"
+ ]
+ },
+ "66": {
+ "hashes": [
+ "0x94d338db2e75740d17df19b0d8a111d5d68b2dfa38819b88929190b4b08b5993"
+ ]
+ },
+ "71": {
+ "hashes": [
+ "0xe9938f6ac90bc4dfdea315ed630b03ad9392b264d362ee1e1b2703fb3db5047a"
+ ]
+ }
+ },
+ "valuetransfer": [
+ {
+ "block": "0x7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "nonce": "0x5",
+ "to": "0xca358758f6d27e6cf45272937977a748fd88391d",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x1c",
+ "r": "0x7252efaed5a8dbefd451c8e39a3940dc5c6a1e81899e0252e892af3060fd90ed",
+ "s": "0x30b6bd9550c9685a1175cece7f680732ac7d3d5445160f8d9309ec1ddba414be",
+ "hash": "0xd04f2bb15db6c40aaf1dcb5babc47914b5f6033b2925cb9daa3c0e0dab493fcb"
+ }
+ },
+ {
+ "block": "0xc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x9",
+ "to": "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x1160803ff1253dead1d84d68a06cb92fcbb265ddb0edb9a5200b28b8c834ce6b",
+ "s": "0x4f1f42c91a7b177f696fc1890de6936097c205f9dcd1d17a4a83ac4d93d84d9c",
+ "hash": "0x778450f223b07f789e343c18207a3388c01070c2f6a89506f2db4c656bc1a37f"
+ }
+ },
+ {
+ "block": "0x11",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd",
+ "to": "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xea20f9d952a58697ffb40cefcab9627f552c9658b3181498fd706418f89a3360",
+ "s": "0x4988596c88fe69f7d032df8e6f515a618a2c2e30f330febb3b548eb4fc1e8ca2",
+ "hash": "0xc2cffc70d847fbe50a53d618de21a24629b97e8dd4c1bcbf73979b2a48ee16df"
+ }
+ },
+ {
+ "block": "0x16",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x11",
+ "to": "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x5f315b1989161bf29054e9e030a05b05b3d7efb4c60e39531b96af1690913f91",
+ "s": "0x6f1d8de5adad6f76ed0d2b4c6885d3a5502c12dae1d124b310e8c8856bd22099",
+ "hash": "0xfa9cd1e12446cd8c23fc76b0ae9beba0ebdc021aa87726b6febcd5ba4a504f01"
+ }
+ },
+ {
+ "block": "0x1b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x15",
+ "to": "0x77adfc95029e73b173f60e556f915b0cd8850848",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x148500c79a2f0d59158458da4e3b2a5ace441bf314942243c9e05da3457d394e",
+ "s": "0x2a83c5f921ffddd3c0b2a05999f820d1d03bce9ac9810941bb286c4db4ce9939",
+ "hash": "0xbfeeb9406545ede112801fe48aeaf30c8e2384739e8e585f1c0e726689abc4b8"
+ }
+ },
+ {
+ "block": "0x20",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x19",
+ "to": "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x14346079d6d3690f923625efde8933b2ad99c2bfda9310983a21b60e3c261d3c",
+ "s": "0x501ae278f370f3c0283fb04f966b6c501cbee0ad4c784f4187e38fcc38a9ccbb",
+ "hash": "0x792614188c26e2f348ac3223813794c60de97b83a298e84f4bae51dda6de140c"
+ }
+ },
+ {
+ "block": "0x25",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x1d",
+ "to": "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x86bc86521cc6091198253d75caf394a8e23fd4fb82b48236d29f81a95aeebec5",
+ "s": "0xae9de4ac4265e3f415514905d8f8c747c959771080fa031dc5fd9b7333ffc28",
+ "hash": "0xc44716fcd212d538b2d143ddec3003b209667bfc977e209e7da1e8bf3c5223b8"
+ }
+ },
+ {
+ "block": "0x2a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x21",
+ "to": "0x684888c0ebb17f374298b65ee2807526c066094c",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x88fa9d9bbc92e44b8edcda67ee23aca611deac4cec336b215fb72547a1d0e07e",
+ "s": "0x297c4d7054cb545bee5221a70454b6270e098f39f91bf25c0526aa8c0a0a441c",
+ "hash": "0xc97ceb5b227ade5363592a68c39dcf1788abbf67b2440934b1ae11cf4b19417c"
+ }
+ },
+ {
+ "block": "0x2f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x25",
+ "to": "0x8a5edab282632443219e051e4ade2d1d5bbc671c",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x649b4ad4dcf07bcfba3dd7afd2ce220d0ae463c1bcc891ab1fcae84eca6fcc69",
+ "s": "0x5c69b0ad46c90eee811e4b71ce0aed22f479c207bee813dac8cce07e5a65adae",
+ "hash": "0xaf340a1b347c756a11e331e771d37d9205eada520f4f0d8d27f725d7c196aed1"
+ }
+ },
+ {
+ "block": "0x34",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x29",
+ "to": "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x7d015036540013eb6aa141a2475fa1dd88d3bee57a67beaf6ef5de8f40969601",
+ "s": "0x4dc750a08f793ff3105479e7919508d14abe56748698375046b995d86267b18c",
+ "hash": "0x07a2a98ac904bcf4c17a773426b34d2b3120af65b12f9bfd437d48c175f364eb"
+ }
+ },
+ {
+ "block": "0x39",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x2d",
+ "to": "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x27f555e9",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xde8b08caa214d0087ffd11206d485cb5cde6a6b6a76b390f53d94a8c16691593",
+ "s": "0x14dfe16ec3e37b8c6d3257deaf987b70b0776b97e4213c1f912c367e7d558370",
+ "yParity": "0x1",
+ "hash": "0xa883c918fb6e392a2448ef21051482bfcbeb5d26b7ebfad2a010a40e188cb43b"
+ }
+ },
+ {
+ "block": "0x3e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x31",
+ "to": "0x62b67e1f685b7fef51102005dddd27774be3fee3",
+ "gas": "0x5208",
+ "gasPrice": "0x14847701",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x6797c616a0fe0fad65b6020fc658541fd25577a3f0e7de47a65690ab81c7a34b",
+ "s": "0x115e6d138f23c97d35422f53aa98d666877d513dbe5d4d8c4654500ead1f4f8f",
+ "hash": "0xb2203865a1a1eace5b82c5154f369d86de851d8c5cd6a19e187f437a1ae28e94"
+ }
+ },
+ {
+ "block": "0x43",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x35",
+ "to": "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xa88fcba",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xdc3f3d86de44ee4dd795ff8ab480f4f5273c8ca61edb4c7561a369c80fbbb983",
+ "s": "0x43a90e087a6f5ba014e17316ec63b97a5a9ada19ab78177c87cb39ded9b37b0d",
+ "yParity": "0x0",
+ "hash": "0x647d637e54f1de1216cdfd83477a067308365c837c6c317febc9d3593907c7cc"
+ }
+ },
+ {
+ "block": "0x48",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x39",
+ "to": "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91",
+ "gas": "0x5208",
+ "gasPrice": "0x568d2fa",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x50fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125c",
+ "s": "0x4f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7",
+ "hash": "0x77050c3fb6b1212cf2f739f781b024b210177b3bcbd5b62e2b3c00f1d41764d1"
+ }
+ },
+ {
+ "block": "0x4c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x3d",
+ "to": "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x32ca5d0",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36",
+ "s": "0x17001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd",
+ "yParity": "0x0",
+ "hash": "0x3e4639389b6a41ff157523860ffc77eb3e66a31aee867eb4148dcc5ee8b3c66f"
+ }
+ },
+ {
+ "block": "0x50",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x41",
+ "to": "0x5c62e091b8c0565f1bafad0dad5934276143ae2c",
+ "gas": "0x5208",
+ "gasPrice": "0x1dce189",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xb82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d5",
+ "s": "0xdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148",
+ "hash": "0x9c9de14ea0ce069a4df1c658e70e48aa7baaf64fddd4ab31bf4cb6d5550a4691"
+ }
+ },
+ {
+ "block": "0x55",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x45",
+ "to": "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xf4dd50",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xe8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8",
+ "s": "0x7c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9",
+ "yParity": "0x0",
+ "hash": "0xff5e3c25f68d57ee002b3b39229ffba0879390475a00fa67a679b707997df530"
+ }
+ },
+ {
+ "block": "0x5a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x49",
+ "to": "0xbbeebd879e1dff6918546dc0c179fdde505f2a21",
+ "gas": "0x5208",
+ "gasPrice": "0x7dbb16",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x2f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849",
+ "s": "0x182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9",
+ "hash": "0xd696adb31daca7c3121e65d11dc00e5d5fdb72c227c701a2925dc19a46fbd43e"
+ }
+ },
+ {
+ "block": "0x5f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x4d",
+ "to": "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x408f23",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6",
+ "s": "0x1cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4",
+ "yParity": "0x1",
+ "hash": "0x385b9f1ba5dbbe419dcbbbbf0840b76b941f3c216d383ec9deb9b1a323ee0cea"
+ }
+ },
+ {
+ "block": "0x64",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x51",
+ "to": "0x18ac3e7343f016890c510e93f935261169d9e3f5",
+ "gas": "0x5208",
+ "gasPrice": "0x212636",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x99aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4",
+ "s": "0x582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a",
+ "hash": "0xd622bf64af8b9bd305e0c86152721b0711b6d24abe3748e2a8cd3a3245f6f878"
+ }
+ },
+ {
+ "block": "0x69",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x55",
+ "to": "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x11056e",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x2a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97",
+ "s": "0x27c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde",
+ "yParity": "0x0",
+ "hash": "0x47efc21f94ef1ef4e9a7d76d9370713acdf8c2b822ad35409566b9251fb0bf5c"
+ }
+ },
+ {
+ "block": "0x6e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x59",
+ "to": "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14",
+ "gas": "0x5208",
+ "gasPrice": "0x8bd6d",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xabbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62c",
+ "s": "0x3aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f",
+ "hash": "0xcf4a0a2b8229fa2f772a90fdef00d073c821c8f56d93bce703007fc5eb528e71"
+ }
+ },
+ {
+ "block": "0x73",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x5d",
+ "to": "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x47cdd",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x2ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196",
+ "s": "0x77a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648",
+ "yParity": "0x1",
+ "hash": "0xded7c87461fb84ffd49426b474741c2eace8982edf07af918bf8794415742384"
+ }
+ },
+ {
+ "block": "0x78",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x61",
+ "to": "0x2d711642b726b04401627ca9fbac32f5c8530fb1",
+ "gas": "0x5208",
+ "gasPrice": "0x24deb",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xb4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6",
+ "s": "0x676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42",
+ "hash": "0x9e2b47fc494a2285f98c89949878e11f7c6d47d24ae95bdab2801333ea8d11a7"
+ }
+ },
+ {
+ "block": "0x7d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x65",
+ "to": "0xd10b36aa74a59bcf4a88185837f658afaf3646ef",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x12eea",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2a",
+ "s": "0x41356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b",
+ "yParity": "0x0",
+ "hash": "0x240efcc882536fad14fcd34be50b508cb4c39b39f1493b8d64682760505b6cf7"
+ }
+ },
+ {
+ "block": "0x82",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x69",
+ "to": "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97",
+ "gas": "0x5208",
+ "gasPrice": "0x9b8c",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x78e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245e",
+ "s": "0x7563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac",
+ "hash": "0xa28d808cbc5ef9e82cd5023ea542fab4052895618b8627c000bb8cc8ccc2e693"
+ }
+ },
+ {
+ "block": "0x87",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x6d",
+ "to": "0x4bfa260a661d68110a7a0a45264d2d43af9727de",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x4fe1",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xbb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8",
+ "s": "0x3b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e",
+ "yParity": "0x1",
+ "hash": "0x83adc66f82e98155384ae9ef0e5be253eba9be959a50bcb48a7a3e6df97d6996"
+ }
+ },
+ {
+ "block": "0x8c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x71",
+ "to": "0x9defb0a9e163278be0e05aa01b312ec78cfa3726",
+ "gas": "0x5208",
+ "gasPrice": "0x2907",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93",
+ "s": "0x581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281",
+ "hash": "0x8e285b12f0ec16977055c8bc17008411883af1b5b33883a8128e50ed3e585685"
+ }
+ },
+ {
+ "block": "0x91",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x75",
+ "to": "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x1513",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81ec",
+ "s": "0x568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1",
+ "yParity": "0x0",
+ "hash": "0x41ca48c0312c6d3fc433f9fd363281dae924885f73ab7466f9e8c97d6ea3b993"
+ }
+ },
+ {
+ "block": "0x96",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x79",
+ "to": "0x84873854dba02cf6a765a6277a311301b2656a7f",
+ "gas": "0x5208",
+ "gasPrice": "0xad4",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1f",
+ "s": "0x5affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f",
+ "hash": "0x7527f1a2c9cad727c70ca0d2117fc52dbfff87962411d0b821e7418a42abd273"
+ }
+ },
+ {
+ "block": "0x9b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x7d",
+ "to": "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x592",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xf9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897",
+ "s": "0x4cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2",
+ "yParity": "0x1",
+ "hash": "0xab2e87692b96ba3083b497227a9a17671bc5eee7ff12d50b850f442a4cdcd8b5"
+ }
+ },
+ {
+ "block": "0xa0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x81",
+ "to": "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168",
+ "gas": "0x5208",
+ "gasPrice": "0x2de",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291",
+ "s": "0x7d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf",
+ "hash": "0x64f8f0ad9c6526cb33e626626a25b8660a546aefa002692e46cd4d0331cd26ed"
+ }
+ },
+ {
+ "block": "0xa5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x85",
+ "to": "0x6922e93e3827642ce4b883c756b31abf80036649",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x17b",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x89e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299",
+ "s": "0x3d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf",
+ "yParity": "0x0",
+ "hash": "0x33b886e4c1c43507a08f0da97d083aa507cf905a90c17ffe20a2a24296f2db31"
+ }
+ },
+ {
+ "block": "0xaa",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x89",
+ "to": "0xbceef655b5a034911f1c3718ce056531b45ef03b",
+ "gas": "0x5208",
+ "gasPrice": "0xc5",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9f",
+ "s": "0x7271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838",
+ "hash": "0xe92638806137815555a0ffe5cc4c2b63b29171fd6f2473736201d8c3c3dbb748"
+ }
+ },
+ {
+ "block": "0xaf",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x8d",
+ "to": "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x68",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122",
+ "s": "0x28e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b",
+ "yParity": "0x1",
+ "hash": "0x3f9133ad0b7430b124cc4b1213bc3fa72be41a58584ca05e8d863ec728890873"
+ }
+ },
+ {
+ "block": "0xb4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x91",
+ "to": "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5",
+ "gas": "0x5208",
+ "gasPrice": "0x39",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x76a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7",
+ "s": "0x1a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c",
+ "hash": "0x201f5041569d4dd9e5cc533867f1864daf1a7ee1a424d703d7aa8a43b07b491d"
+ }
+ },
+ {
+ "block": "0xb9",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x95",
+ "to": "0x04d6c0c946716aac894fc1653383543a91faab60",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x20",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x39c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8a",
+ "s": "0x5ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a",
+ "yParity": "0x0",
+ "hash": "0xf83394fd19018fd54a5004121bc780995f99cb47832ddb11f7c50bf507606202"
+ }
+ },
+ {
+ "block": "0xbe",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x99",
+ "to": "0x478508483cbb05defd7dcdac355dadf06282a6f2",
+ "gas": "0x5208",
+ "gasPrice": "0x13",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178",
+ "s": "0x2ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1",
+ "hash": "0x586f6726554ffef84726c93123de9fb1f0194dfd55ed7ca3ceae67e27b1f4fef"
+ }
+ },
+ {
+ "block": "0xc3",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x9d",
+ "to": "0xae3f4619b0413d70d3004b9131c3752153074e45",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xc",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x7cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54",
+ "s": "0x3bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677",
+ "yParity": "0x1",
+ "hash": "0xadfacbcb99b52f33c74cbd7c45d1f0d31efc4a3f025f9832cf28e666c79c8e4c"
+ }
+ },
+ {
+ "block": "0xc8",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa1",
+ "to": "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f",
+ "gas": "0x5208",
+ "gasPrice": "0x9",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x15f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391",
+ "s": "0x3b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8",
+ "hash": "0xed00ce6bd533009ddfb39d7735f1e2c468a231cf4c5badb59d1e1234c5fe3794"
+ }
+ },
+ {
+ "block": "0xcd",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa5",
+ "to": "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x4f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25",
+ "s": "0x312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a",
+ "yParity": "0x0",
+ "hash": "0x883c915c1ef312df1e499ef78d09767a374706d8ec89af9c65c46acd675bf817"
+ }
+ },
+ {
+ "block": "0xd2",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa9",
+ "to": "0x85f97e04d754c81dac21f0ce857adc81170d08c6",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0",
+ "s": "0x28cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2",
+ "hash": "0x27d83955c23134e42c9beaa88332f770d09e589354c1047870328b7a2f8612c9"
+ }
+ },
+ {
+ "block": "0xd7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xad",
+ "to": "0x414a21e525a759e3ffeb22556be6348a92d5a13e",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x47b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab66",
+ "s": "0xb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9",
+ "yParity": "0x1",
+ "hash": "0xb75adb0bd26a8060f67c947b699471d71a66c61f2b8c6903a776c3eca7ad731e"
+ }
+ },
+ {
+ "block": "0xdc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb1",
+ "to": "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xc71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0",
+ "s": "0x3bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde",
+ "hash": "0x0301d78cc4bc0330c468026de4671377a07560c2356293c2af44334e6424361a"
+ }
+ },
+ {
+ "block": "0xe1",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb5",
+ "to": "0xf031efa58744e97a34555ca98621d4e8a52ceb5f",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x99b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348",
+ "s": "0x56e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3",
+ "yParity": "0x1",
+ "hash": "0x6e07cf26de1881f062629d9efa026c55b9e8084082086e974ddeb66654cd9530"
+ }
+ },
+ {
+ "block": "0xe6",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb9",
+ "to": "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xd2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353",
+ "s": "0x542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3",
+ "hash": "0xd77aeb22fbd8f99b75c970995d226b6985f2dcac6f22d65aa5d492d66e90f53f"
+ }
+ },
+ {
+ "block": "0xeb",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xbd",
+ "to": "0xf8d20e598df20877e4d826246fc31ffb4615cbc0",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xc982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350",
+ "s": "0x7a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e",
+ "yParity": "0x1",
+ "hash": "0x597bc815e8b0c315e692257aabe4ecfce7055fa3659f02dd8444c7d58c9055f3"
+ }
+ },
+ {
+ "block": "0xf0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc1",
+ "to": "0xfde502858306c235a3121e42326b53228b7ef469",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x3d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34",
+ "s": "0x4278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17",
+ "hash": "0xe9c1c01813ee52f2a9b8aa63e200714c7527315caf55d054890c10acc73c6cec"
+ }
+ },
+ {
+ "block": "0xf5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc5",
+ "to": "0x27abdeddfe8503496adeb623466caa47da5f63ab",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xdeade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25",
+ "s": "0x65f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283",
+ "yParity": "0x1",
+ "hash": "0x2beff883cd58f8d155069d608dfc47f730a07f1ed361987b008c17a4b8b84a4b"
+ }
+ },
+ {
+ "block": "0xfa",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc9",
+ "to": "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694",
+ "s": "0x60f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a",
+ "hash": "0x084d5438c574a2332976d95cfae552edb797001b5af69eacf4486538ab4bdbd2"
+ }
+ },
+ {
+ "block": "0xff",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xcd",
+ "to": "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x54eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32b",
+ "s": "0x59af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3",
+ "yParity": "0x0",
+ "hash": "0xecce661913425dbe38e2d30e7ec20ead32185d76f516525148d2647ee94aac8e"
+ }
+ },
+ {
+ "block": "0x104",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd1",
+ "to": "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2ade",
+ "s": "0x5e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b",
+ "hash": "0x0d903532e3740a8fb644943befee0187e6180eb31a327afc73e042ec314c02cc"
+ }
+ },
+ {
+ "block": "0x109",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd5",
+ "to": "0xac9e61d54eb6967e212c06aab15408292f8558c4",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100a",
+ "s": "0x7e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e",
+ "yParity": "0x1",
+ "hash": "0xdd62d8c48dd14b156b3ea74d123fe3ddd7bc7700d0f189df3761ec7a8d65d1e9"
+ }
+ },
+ {
+ "block": "0x10e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd9",
+ "to": "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466c",
+ "s": "0x2043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc",
+ "hash": "0x284452da997f42dbe0e511078f5005514fdeda8d0905439fe2f3a5ecc3aec1ac"
+ }
+ },
+ {
+ "block": "0x113",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xdd",
+ "to": "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x4330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85",
+ "s": "0x7977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7",
+ "yParity": "0x1",
+ "hash": "0xd667f29e2cccf282a82791cb46f9181ad04c8179bc11af957c499b3627907a6f"
+ }
+ },
+ {
+ "block": "0x118",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe1",
+ "to": "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xcfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690",
+ "s": "0x1e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e",
+ "hash": "0x935596bc447ea87dca90e3bac15f679129af2c813abe1657811f70dcafe660c2"
+ }
+ },
+ {
+ "block": "0x11d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe5",
+ "to": "0xaf2c6f1512d1cabedeaf129e0643863c57419732",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xc23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516",
+ "s": "0x3f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4",
+ "yParity": "0x1",
+ "hash": "0xc659a1be386492afe2ca97cbbe9d1645763b502030c17e3acf9d539e22b74093"
+ }
+ },
+ {
+ "block": "0x122",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe9",
+ "to": "0xb70654fead634e1ede4518ef34872c9d4f083a53",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3d",
+ "s": "0x4e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff",
+ "hash": "0x6f7f93620049c80ba6429e3c2f7563f7048f725f245c22bcc6de438fd394bb7e"
+ }
+ },
+ {
+ "block": "0x127",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xed",
+ "to": "0xbe3eea9a483308cb3134ce068e77b56e7c25af19",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60",
+ "s": "0x2c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5",
+ "yParity": "0x0",
+ "hash": "0xe48311c620199dfc77bc280caa0a1bcbbd00457b079a7154a6f8bc229beb41f1"
+ }
+ },
+ {
+ "block": "0x12c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf1",
+ "to": "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xe3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5",
+ "s": "0x51429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e",
+ "hash": "0xa960e3583c41a164dc743eac939626f891f20f7dfdf71f204c2f84ca1087ae90"
+ }
+ },
+ {
+ "block": "0x131",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf5",
+ "to": "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482",
+ "s": "0x2ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec",
+ "yParity": "0x1",
+ "hash": "0xc7ccef252840e9fc1821f2c2eb0ca8c9508ff3f4c23f85322e09dd9313849694"
+ }
+ },
+ {
+ "block": "0x136",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf9",
+ "to": "0x17333b15b4a5afd16cac55a104b554fc63cc8731",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aa",
+ "s": "0x657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a",
+ "hash": "0x45ed5258df6ecd5ba8b99db384e39d22c193662830e79f972547d81e3857cc70"
+ }
+ },
+ {
+ "block": "0x13b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xfd",
+ "to": "0xd20b702303d7d7c8afe50344d66a8a711bae1425",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x67bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244",
+ "s": "0x76661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a",
+ "yParity": "0x1",
+ "hash": "0xa3b085cc524be64d822be105f3bb92c05c773cb93bffc774ba9aac21f9603ce6"
+ }
+ },
+ {
+ "block": "0x140",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x101",
+ "to": "0xdd1e2826c0124a6d4f7397a5a71f633928926c06",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x1f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6",
+ "s": "0x1960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e",
+ "hash": "0x34671329e36adeee3261ea7313388804f481e6a0e2f77cce6961aed112498803"
+ }
+ },
+ {
+ "block": "0x145",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x105",
+ "to": "0x1219c38638722b91f3a909f930d3acc16e309804",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x63adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98",
+ "s": "0x56f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa",
+ "yParity": "0x1",
+ "hash": "0x7bfa3e961b16291e9ee2f4dc0b6489bb0b12ff7a6ed6491c100dd1041472ff9e"
+ }
+ },
+ {
+ "block": "0x14a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x109",
+ "to": "0x1f5746736c7741ae3e8fa0c6e947cade81559a86",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xedd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7d",
+ "s": "0x68cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80",
+ "hash": "0x90ea391ff615d345ad4e35e53af26e283fc2fd9ecb3221a9610fb2a376c38caf"
+ }
+ },
+ {
+ "block": "0x14f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x10d",
+ "to": "0x9ae62b6d840756c238b5ce936b910bb99d565047",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x25cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30",
+ "s": "0x193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3",
+ "yParity": "0x0",
+ "hash": "0xa1ea0831d6727a0e7316822d3cc3815f1e2ba71e124fcd8b886610d5d42fd5ff"
+ }
+ },
+ {
+ "block": "0x154",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x111",
+ "to": "0xb55a3d332d267493105927b892545d2cd4c83bd6",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x73cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1",
+ "s": "0x388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8",
+ "hash": "0xd30ff6e59e0e1278dab8083cb01e1e66900adc72cc4263cbdffc98e08a728b89"
+ }
+ },
+ {
+ "block": "0x159",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x115",
+ "to": "0xb68176634dde4d9402ecb148265db047d17cb4ab",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59b",
+ "s": "0x6a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6",
+ "yParity": "0x0",
+ "hash": "0x5565d4f07ad007f4bfe27837904f2ce365cff6c036aa5169df651f217944b1f4"
+ }
+ },
+ {
+ "block": "0x15e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x119",
+ "to": "0xdfe052578c96df94fa617102199e66110181ed2c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x20ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1",
+ "s": "0xf72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f",
+ "hash": "0x9055a34f1c764ce297f1bce6c94680a0e8d532debeb6af642c956122f4c7d079"
+ }
+ },
+ {
+ "block": "0x163",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x11d",
+ "to": "0x33fc6e8ad066231eb5527d1a39214c1eb390985d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1c",
+ "s": "0x269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd",
+ "yParity": "0x1",
+ "hash": "0x0aa77f1fa0e9ab541616fb3104788109f84010d4b410508e5779f052ee49c5b9"
+ }
+ },
+ {
+ "block": "0x168",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x121",
+ "to": "0x662fb906c0fb671022f9914d6bba12250ea6adfb",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xd3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7",
+ "s": "0x202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613",
+ "hash": "0x01bdc2fb7f53293c98e430dc42b1ef18773493f0f1bd03460eb45e438168048d"
+ }
+ },
+ {
+ "block": "0x16d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x125",
+ "to": "0xf1fc98c0060f0d12ae263986be65770e2ae42eae",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210",
+ "s": "0xa96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b",
+ "yParity": "0x0",
+ "hash": "0x36cf0f21e046b484333889a22e4880ad05807f2922340e6e822591cfa5138815"
+ }
+ },
+ {
+ "block": "0x172",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x129",
+ "to": "0xa92bb60b61e305ddd888015189d6591b0eab0233",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dd",
+ "s": "0x74494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347",
+ "hash": "0x8cb5e311a3e79a31c06afaecbbf9c814759f039f55b06ead4e8a1c2933766c8c"
+ }
+ },
+ {
+ "block": "0x177",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x12d",
+ "to": "0x469542b3ece7ae501372a11c673d7627294a85ca",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fb",
+ "s": "0x21a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197",
+ "yParity": "0x0",
+ "hash": "0x55c8ee8da8d54305ca22c9d7b4226539a60741ed599327d33013f8d0385c61bd"
+ }
+ },
+ {
+ "block": "0x17c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x131",
+ "to": "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xfd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24",
+ "s": "0x542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a",
+ "hash": "0x3964c50008f0dce6974ef2c088a84207191eb56ab4ac86cbf5d149a661ecb479"
+ }
+ },
+ {
+ "block": "0x181",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x135",
+ "to": "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x3931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6",
+ "s": "0x215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f",
+ "yParity": "0x0",
+ "hash": "0x23583194a4443b0144115327770bf71f645283515ca26fc775dd23244a876e83"
+ }
+ },
+ {
+ "block": "0x186",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x139",
+ "to": "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xa38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751",
+ "s": "0x67c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f",
+ "hash": "0x41019c72018f2f499368e96aed89293b24873f611018c3787eeb81a0a01b667b"
+ }
+ },
+ {
+ "block": "0x18b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x13d",
+ "to": "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x6faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07b",
+ "s": "0x656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6",
+ "yParity": "0x1",
+ "hash": "0x054500013715ec41cb39492f2856925c7f22f80fd22365f19de8124b14e77e90"
+ }
+ },
+ {
+ "block": "0x190",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x141",
+ "to": "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836a",
+ "s": "0x598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94",
+ "hash": "0x1b562d975247f54df92dc775c61ef8fb004714fd57d0c804dd64e44be2f10cb5"
+ }
+ },
+ {
+ "block": "0x195",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x145",
+ "to": "0x360671abc40afd33ae0091e87e589fc320bf9e3d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87",
+ "s": "0x2c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069",
+ "yParity": "0x0",
+ "hash": "0x3e3bec1253082bf314cb1155ef241912bc842b8ced86b70e5e3b24585a130d66"
+ }
+ },
+ {
+ "block": "0x19a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x149",
+ "to": "0x579ab019e6b461188300c7fb202448d34669e5ff",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xde600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dc",
+ "s": "0x47d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634",
+ "hash": "0x519fbf530d16289510ebb27b099ad16ad03e72227497db7a62e6c0e89d3a708a"
+ }
+ },
+ {
+ "block": "0x19f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x14d",
+ "to": "0x88654f0e7be1751967bba901ed70257a3cb79940",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xa79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0",
+ "s": "0x750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6",
+ "yParity": "0x1",
+ "hash": "0x6364bf260fee1aea143ec4a4c596d64e15252f8fa4c7ab7ae69d51ff4cbd343b"
+ }
+ },
+ {
+ "block": "0x1a4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x151",
+ "to": "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xc37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618",
+ "s": "0x190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892",
+ "hash": "0x2ee70986d957daba62588ac40c9bf75f6707a34dc5ef5897ae7cd3998f2e05bc"
+ }
+ },
+ {
+ "block": "0x1a9",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x155",
+ "to": "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x7a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09",
+ "s": "0x75f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8",
+ "yParity": "0x0",
+ "hash": "0xbaf8e87ba94a0d70e37443c4475b2525806827b3ae964b30eb4dad7936b2eb6e"
+ }
+ },
+ {
+ "block": "0x1ae",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x159",
+ "to": "0xc305dd6cfc073cfe5e194fc817536c419410a27d",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810",
+ "s": "0x4ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9",
+ "hash": "0x4a84eeb0addd194ae92631aa43ed4f4fece16258bcbbc91de6324e20bde0f914"
+ }
+ },
+ {
+ "block": "0x1b3",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x15d",
+ "to": "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88",
+ "s": "0x17f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b",
+ "yParity": "0x1",
+ "hash": "0x01b1e85401ca88bc02c33956d0bfeea9ec0b6c916f1478d4eae39818e999cb74"
+ }
+ },
+ {
+ "block": "0x1b8",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x161",
+ "to": "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892",
+ "s": "0x70505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed",
+ "hash": "0xf8c7948d4418ad9948d7352c6c21dcb5b7f72664dfcfe553dfc444df7afc9c0b"
+ }
+ },
+ {
+ "block": "0x1bd",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x165",
+ "to": "0x046dc70a4eba21473beb6d9460d880b8cfd66613",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996e",
+ "s": "0x418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387",
+ "yParity": "0x0",
+ "hash": "0xf09a7e0da3b14049923d019fb5d457531ddaa4456cf84124a17479b0bfd6261b"
+ }
+ },
+ {
+ "block": "0x1c2",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x169",
+ "to": "0x104eb07eb9517a895828ab01a3595d3b94c766d5",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0a",
+ "s": "0x1f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563",
+ "hash": "0x00c458459a2d2f501907a6a4122fba7ae70fb3ef632676e492912231022f80c8"
+ }
+ },
+ {
+ "block": "0x1c7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x16d",
+ "to": "0x46b61db0aac95a332cecadad86e52531e578cf1f",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008b",
+ "s": "0x6f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8",
+ "yParity": "0x0",
+ "hash": "0x6603c100a34224ddb8aaeb9e234f0c611d40a5df807de68803b71e0ff0f3aea8"
+ }
+ },
+ {
+ "block": "0x1cc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x171",
+ "to": "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xa755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1",
+ "s": "0x67d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d",
+ "hash": "0x46e00cb4ede9be515c8910a31881df229ebb2804722ad9d6723e1101a87f1889"
+ }
+ },
+ {
+ "block": "0x1d1",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x175",
+ "to": "0x23e6931c964e77b02506b08ebf115bad0e1eca66",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242",
+ "s": "0x2b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7",
+ "yParity": "0x0",
+ "hash": "0xa5b751caaaff89a472fb427c17ac7637b4a9de7cda34beaaf891516278655479"
+ }
+ },
+ {
+ "block": "0x1d6",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x179",
+ "to": "0x878dedd9474cfa24d91bccc8b771e180cf01ac40",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367",
+ "s": "0x23756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8",
+ "hash": "0x2e232fb6d73423c9dcaff38257d36fcad74a2c627a70030b43a0bed36d136625"
+ }
+ },
+ {
+ "block": "0x1db",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x17d",
+ "to": "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xd3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4",
+ "s": "0x368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30",
+ "yParity": "0x1",
+ "hash": "0xc80615944f9bfeb945b7416052667eec0a78b2f3beb7c2811ebb9e9210e45c4c"
+ }
+ },
+ {
+ "block": "0x1e0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x181",
+ "to": "0x50996999ff63a9a1a07da880af8f8c745a7fe72c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6a",
+ "s": "0x7fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4",
+ "hash": "0x8c1f1466ce25a97e88ab37bc9b5362eaf95fb523fb80d176429fa41c2fa2d629"
+ }
+ },
+ {
+ "block": "0x1e5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x185",
+ "to": "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xd4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8",
+ "s": "0x64c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a",
+ "yParity": "0x0",
+ "hash": "0x969e178ea1a76626b96bf06e207edb6299c36c6a14e46462960832feb93f6d42"
+ }
+ },
+ {
+ "block": "0x1ea",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x189",
+ "to": "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xd33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5c",
+ "s": "0x667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316",
+ "hash": "0xa35c19e4e8154c35656544b92e88fb62c4210e38f09608248e2a99841ac99964"
+ }
+ },
+ {
+ "block": "0x1ef",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x18d",
+ "to": "0x6e3d512a9328fa42c7ca1e20064071f88958ed93",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3d",
+ "s": "0x5d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa",
+ "yParity": "0x0",
+ "hash": "0xeb282a48d309db881eead661ee7c64696b2699fa7c431d39a573ecaa0bc31052"
+ }
+ },
+ {
+ "block": "0x1f4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x191",
+ "to": "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x85b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7",
+ "s": "0x52e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc",
+ "hash": "0x22e616c85493bcd23147d1c9f5dd081b32daf5c7b3e824f61b5fc1bd34a47e67"
+ }
+ }
+ ],
+ "withdrawals": {
+ "101": {
+ "withdrawals": [
+ {
+ "index": "0x4",
+ "validatorIndex": "0x5",
+ "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "106": {
+ "withdrawals": [
+ {
+ "index": "0x5",
+ "validatorIndex": "0x5",
+ "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "111": {
+ "withdrawals": [
+ {
+ "index": "0x6",
+ "validatorIndex": "0x5",
+ "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "116": {
+ "withdrawals": [
+ {
+ "index": "0x7",
+ "validatorIndex": "0x5",
+ "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "121": {
+ "withdrawals": [
+ {
+ "index": "0x8",
+ "validatorIndex": "0x5",
+ "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "126": {
+ "withdrawals": [
+ {
+ "index": "0x9",
+ "validatorIndex": "0x5",
+ "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "131": {
+ "withdrawals": [
+ {
+ "index": "0xa",
+ "validatorIndex": "0x5",
+ "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "136": {
+ "withdrawals": [
+ {
+ "index": "0xb",
+ "validatorIndex": "0x5",
+ "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "141": {
+ "withdrawals": [
+ {
+ "index": "0xc",
+ "validatorIndex": "0x5",
+ "address": "0x075198bfe61765d35f990debe90959d438a943ce",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "146": {
+ "withdrawals": [
+ {
+ "index": "0xd",
+ "validatorIndex": "0x5",
+ "address": "0x956062137518b270d730d4753000896de17c100a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "151": {
+ "withdrawals": [
+ {
+ "index": "0xe",
+ "validatorIndex": "0x5",
+ "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "156": {
+ "withdrawals": [
+ {
+ "index": "0xf",
+ "validatorIndex": "0x5",
+ "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "161": {
+ "withdrawals": [
+ {
+ "index": "0x10",
+ "validatorIndex": "0x5",
+ "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "166": {
+ "withdrawals": [
+ {
+ "index": "0x11",
+ "validatorIndex": "0x5",
+ "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "171": {
+ "withdrawals": [
+ {
+ "index": "0x12",
+ "validatorIndex": "0x5",
+ "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "176": {
+ "withdrawals": [
+ {
+ "index": "0x13",
+ "validatorIndex": "0x5",
+ "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "181": {
+ "withdrawals": [
+ {
+ "index": "0x14",
+ "validatorIndex": "0x5",
+ "address": "0x892f60b39450a0e770f00a836761c8e964fd7467",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "186": {
+ "withdrawals": [
+ {
+ "index": "0x15",
+ "validatorIndex": "0x5",
+ "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "191": {
+ "withdrawals": [
+ {
+ "index": "0x16",
+ "validatorIndex": "0x5",
+ "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "196": {
+ "withdrawals": [
+ {
+ "index": "0x17",
+ "validatorIndex": "0x5",
+ "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "201": {
+ "withdrawals": [
+ {
+ "index": "0x18",
+ "validatorIndex": "0x5",
+ "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "206": {
+ "withdrawals": [
+ {
+ "index": "0x19",
+ "validatorIndex": "0x5",
+ "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "211": {
+ "withdrawals": [
+ {
+ "index": "0x1a",
+ "validatorIndex": "0x5",
+ "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "216": {
+ "withdrawals": [
+ {
+ "index": "0x1b",
+ "validatorIndex": "0x5",
+ "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "221": {
+ "withdrawals": [
+ {
+ "index": "0x1c",
+ "validatorIndex": "0x5",
+ "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "226": {
+ "withdrawals": [
+ {
+ "index": "0x1d",
+ "validatorIndex": "0x5",
+ "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "231": {
+ "withdrawals": [
+ {
+ "index": "0x1e",
+ "validatorIndex": "0x5",
+ "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "236": {
+ "withdrawals": [
+ {
+ "index": "0x1f",
+ "validatorIndex": "0x5",
+ "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "241": {
+ "withdrawals": [
+ {
+ "index": "0x20",
+ "validatorIndex": "0x5",
+ "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "246": {
+ "withdrawals": [
+ {
+ "index": "0x21",
+ "validatorIndex": "0x5",
+ "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "251": {
+ "withdrawals": [
+ {
+ "index": "0x22",
+ "validatorIndex": "0x5",
+ "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "256": {
+ "withdrawals": [
+ {
+ "index": "0x23",
+ "validatorIndex": "0x5",
+ "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "261": {
+ "withdrawals": [
+ {
+ "index": "0x24",
+ "validatorIndex": "0x5",
+ "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "266": {
+ "withdrawals": [
+ {
+ "index": "0x25",
+ "validatorIndex": "0x5",
+ "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "271": {
+ "withdrawals": [
+ {
+ "index": "0x26",
+ "validatorIndex": "0x5",
+ "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "276": {
+ "withdrawals": [
+ {
+ "index": "0x27",
+ "validatorIndex": "0x5",
+ "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "281": {
+ "withdrawals": [
+ {
+ "index": "0x28",
+ "validatorIndex": "0x5",
+ "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "286": {
+ "withdrawals": [
+ {
+ "index": "0x29",
+ "validatorIndex": "0x5",
+ "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "291": {
+ "withdrawals": [
+ {
+ "index": "0x2a",
+ "validatorIndex": "0x5",
+ "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "296": {
+ "withdrawals": [
+ {
+ "index": "0x2b",
+ "validatorIndex": "0x5",
+ "address": "0x1c972398125398a3665f212930758ae9518a8c94",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "301": {
+ "withdrawals": [
+ {
+ "index": "0x2c",
+ "validatorIndex": "0x5",
+ "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "306": {
+ "withdrawals": [
+ {
+ "index": "0x2d",
+ "validatorIndex": "0x5",
+ "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "311": {
+ "withdrawals": [
+ {
+ "index": "0x2e",
+ "validatorIndex": "0x5",
+ "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "316": {
+ "withdrawals": [
+ {
+ "index": "0x2f",
+ "validatorIndex": "0x5",
+ "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "321": {
+ "withdrawals": [
+ {
+ "index": "0x30",
+ "validatorIndex": "0x5",
+ "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "326": {
+ "withdrawals": [
+ {
+ "index": "0x31",
+ "validatorIndex": "0x5",
+ "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "331": {
+ "withdrawals": [
+ {
+ "index": "0x32",
+ "validatorIndex": "0x5",
+ "address": "0x984c16459ded76438d98ce9b608f175c28a910a0",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "336": {
+ "withdrawals": [
+ {
+ "index": "0x33",
+ "validatorIndex": "0x5",
+ "address": "0x2847213288f0988543a76512fab09684131809d9",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "341": {
+ "withdrawals": [
+ {
+ "index": "0x34",
+ "validatorIndex": "0x5",
+ "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "346": {
+ "withdrawals": [
+ {
+ "index": "0x35",
+ "validatorIndex": "0x5",
+ "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "351": {
+ "withdrawals": [
+ {
+ "index": "0x36",
+ "validatorIndex": "0x5",
+ "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "356": {
+ "withdrawals": [
+ {
+ "index": "0x37",
+ "validatorIndex": "0x5",
+ "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "361": {
+ "withdrawals": [
+ {
+ "index": "0x38",
+ "validatorIndex": "0x5",
+ "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "366": {
+ "withdrawals": [
+ {
+ "index": "0x39",
+ "validatorIndex": "0x5",
+ "address": "0x19041ad672875015bc4041c24b581eafc0869aab",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "371": {
+ "withdrawals": [
+ {
+ "index": "0x3a",
+ "validatorIndex": "0x5",
+ "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "376": {
+ "withdrawals": [
+ {
+ "index": "0x3b",
+ "validatorIndex": "0x5",
+ "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "381": {
+ "withdrawals": [
+ {
+ "index": "0x3c",
+ "validatorIndex": "0x5",
+ "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "386": {
+ "withdrawals": [
+ {
+ "index": "0x3d",
+ "validatorIndex": "0x5",
+ "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "391": {
+ "withdrawals": [
+ {
+ "index": "0x3e",
+ "validatorIndex": "0x5",
+ "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "396": {
+ "withdrawals": [
+ {
+ "index": "0x3f",
+ "validatorIndex": "0x5",
+ "address": "0x6d09a879576c0d941bea7833fb2285051b10d511",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "401": {
+ "withdrawals": [
+ {
+ "index": "0x40",
+ "validatorIndex": "0x5",
+ "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "406": {
+ "withdrawals": [
+ {
+ "index": "0x41",
+ "validatorIndex": "0x5",
+ "address": "0x6510225e743d73828aa4f73a3133818490bd8820",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "411": {
+ "withdrawals": [
+ {
+ "index": "0x42",
+ "validatorIndex": "0x5",
+ "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "416": {
+ "withdrawals": [
+ {
+ "index": "0x43",
+ "validatorIndex": "0x5",
+ "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "421": {
+ "withdrawals": [
+ {
+ "index": "0x44",
+ "validatorIndex": "0x5",
+ "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "426": {
+ "withdrawals": [
+ {
+ "index": "0x45",
+ "validatorIndex": "0x5",
+ "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "431": {
+ "withdrawals": [
+ {
+ "index": "0x46",
+ "validatorIndex": "0x5",
+ "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "436": {
+ "withdrawals": [
+ {
+ "index": "0x47",
+ "validatorIndex": "0x5",
+ "address": "0x5123198d8a827fe0c788c409e7d2068afde64339",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "441": {
+ "withdrawals": [
+ {
+ "index": "0x48",
+ "validatorIndex": "0x5",
+ "address": "0xd39b94587711196640659ec81855bcf397e419ff",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "446": {
+ "withdrawals": [
+ {
+ "index": "0x49",
+ "validatorIndex": "0x5",
+ "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "451": {
+ "withdrawals": [
+ {
+ "index": "0x4a",
+ "validatorIndex": "0x5",
+ "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "456": {
+ "withdrawals": [
+ {
+ "index": "0x4b",
+ "validatorIndex": "0x5",
+ "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "461": {
+ "withdrawals": [
+ {
+ "index": "0x4c",
+ "validatorIndex": "0x5",
+ "address": "0x48701721ec0115f04bc7404058f6c0f386946e09",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "466": {
+ "withdrawals": [
+ {
+ "index": "0x4d",
+ "validatorIndex": "0x5",
+ "address": "0x706be462488699e89b722822dcec9822ad7d05a7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "471": {
+ "withdrawals": [
+ {
+ "index": "0x4e",
+ "validatorIndex": "0x5",
+ "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "476": {
+ "withdrawals": [
+ {
+ "index": "0x4f",
+ "validatorIndex": "0x5",
+ "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "481": {
+ "withdrawals": [
+ {
+ "index": "0x50",
+ "validatorIndex": "0x5",
+ "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "486": {
+ "withdrawals": [
+ {
+ "index": "0x51",
+ "validatorIndex": "0x5",
+ "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "491": {
+ "withdrawals": [
+ {
+ "index": "0x52",
+ "validatorIndex": "0x5",
+ "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "496": {
+ "withdrawals": [
+ {
+ "index": "0x53",
+ "validatorIndex": "0x5",
+ "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "81": {
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x5",
+ "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "86": {
+ "withdrawals": [
+ {
+ "index": "0x1",
+ "validatorIndex": "0x5",
+ "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "91": {
+ "withdrawals": [
+ {
+ "index": "0x2",
+ "validatorIndex": "0x5",
+ "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "96": {
+ "withdrawals": [
+ {
+ "index": "0x3",
+ "validatorIndex": "0x5",
+ "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c",
+ "amount": "0x64"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/transaction.go b/cmd/devp2p/internal/ethtest/transaction.go
index 256265b335..e90a808fad 100644
--- a/cmd/devp2p/internal/ethtest/transaction.go
+++ b/cmd/devp2p/internal/ethtest/transaction.go
@@ -19,485 +19,161 @@ package ethtest
import (
"errors"
"fmt"
- "math/big"
- "strings"
+ "os"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/internal/utesting"
- "github.com/ethereum/go-ethereum/params"
)
-// var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
-var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
-
-func (s *Suite) sendSuccessfulTxs(t *utesting.T) error {
- tests := []*types.Transaction{
- getNextTxFromChain(s),
- unknownTx(s),
- }
- for i, tx := range tests {
- if tx == nil {
- return errors.New("could not find tx to send")
- }
-
- t.Logf("Testing tx propagation %d: sending tx %v %v %v\n", i, tx.Hash().String(), tx.GasPrice(), tx.Gas())
- // get previous tx if exists for reference in case of old tx propagation
- var prevTx *types.Transaction
- if i != 0 {
- prevTx = tests[i-1]
- }
- // write tx to connection
- if err := sendSuccessfulTx(s, tx, prevTx); err != nil {
- return fmt.Errorf("send successful tx test failed: %v", err)
- }
- }
-
- return nil
-}
-
-// nolint:typecheck, gocognit
-func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction) error {
- sendConn, recvConn, err := s.createSendAndRecvConns()
+// sendTxs sends the given transactions to the node and
+// expects the node to accept and propagate them.
+func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error {
+ // Open sending conn.
+ sendConn, err := s.dial()
if err != nil {
return err
}
defer sendConn.Close()
- defer recvConn.Close()
-
if err = sendConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
- // Send the transaction
- if err = sendConn.Write(&Transactions{tx}); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
- // peer receiving connection to node
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- // update last nonce seen
- nonce = tx.Nonce()
-
- // Wait for the transaction announcement
- for {
- switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
- case *Transactions:
- recTxs := *msg
- // if you receive an old tx propagation, read from connection again
- if len(recTxs) == 1 && prevTx != nil {
- if recTxs[0] == prevTx {
- continue
- }
- }
-
- for _, gotTx := range recTxs {
- if gotTx.Hash() == tx.Hash() {
- // Ok
- return nil
- }
- }
-
- return fmt.Errorf("missing transaction: got %v missing %v", recTxs, tx.Hash())
- case *NewPooledTransactionHashes66:
- txHashes := *msg
- // if you receive an old tx propagation, read from connection again
- if len(txHashes) == 1 && prevTx != nil {
- if txHashes[0] == prevTx.Hash() {
- continue
- }
- }
-
- for _, gotHash := range txHashes {
- if gotHash == tx.Hash() {
- // Ok
- return nil
- }
- }
-
- return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
- case *NewPooledTransactionHashes:
- txHashes := msg.Hashes
- if len(txHashes) != len(msg.Sizes) {
- return fmt.Errorf("invalid msg size lengths: hashes: %v sizes: %v", len(txHashes), len(msg.Sizes))
- }
-
- if len(txHashes) != len(msg.Types) {
- return fmt.Errorf("invalid msg type lengths: hashes: %v types: %v", len(txHashes), len(msg.Types))
- }
- // if you receive an old tx propagation, read from connection again
- if len(txHashes) == 1 && prevTx != nil {
- if txHashes[0] == prevTx.Hash() {
- continue
- }
- }
-
- for index, gotHash := range txHashes {
- if gotHash == tx.Hash() {
- if msg.Sizes[index] != uint32(tx.Size()) {
- return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size())
- }
-
- if msg.Types[index] != tx.Type() {
- return fmt.Errorf("invalid tx type: got %v want %v", msg.Types[index], tx.Type())
- }
- // Ok
- return nil
- }
- }
-
- return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
-
- default:
- return fmt.Errorf("unexpected message in sendSuccessfulTx: %s", pretty.Sdump(msg))
- }
- }
-}
-
-func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
- badTxs := []*types.Transaction{
- getOldTxFromChain(s),
- invalidNonceTx(s),
- hugeAmount(s),
- hugeGasPrice(s),
- hugeData(s),
- }
-
- // setup receiving connection before sending malicious txs
+ // Open receiving conn.
recvConn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
-
- defer recvConn.Close()
-
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- for i, tx := range badTxs {
- t.Logf("Testing malicious tx propagation: %v\n", i)
-
- if err = sendMaliciousTx(s, tx); err != nil {
- return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
- }
- }
- // check to make sure bad txs aren't propagated
- return checkMaliciousTxPropagation(s, badTxs, recvConn)
-}
-
-func sendMaliciousTx(s *Suite, tx *types.Transaction) error {
- conn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
-
- defer conn.Close()
-
- if err = conn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- // write malicious tx
- if err = conn.Write(&Transactions{tx}); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
-
- return nil
-}
-
-var nonce = uint64(99)
-
-// sendMultipleSuccessfulTxs sends the given transactions to the node and
-// expects the node to accept and propagate them.
-func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error {
- txMsg := Transactions(txs)
- t.Logf("sending %d txs\n", len(txs))
-
- sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil {
return err
}
-
- defer sendConn.Close()
defer recvConn.Close()
-
- if err = sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
- // Send the transactions
- if err = sendConn.Write(&txMsg); err != nil {
+ if err = sendConn.Write(ethProto, eth.TransactionsMsg, eth.TransactionsPacket(txs)); err != nil {
return fmt.Errorf("failed to write message to connection: %v", err)
}
- // update nonce
- nonce = txs[len(txs)-1].Nonce()
+ var (
+ got = make(map[common.Hash]bool)
+ end = time.Now().Add(timeout)
+ )
- // Wait for the transaction announcement(s) and make sure all sent txs are being propagated.
- // all txs should be announced within a couple announcements.
- recvHashes := make([]common.Hash, 0)
-
- for i := 0; i < 20; i++ {
- switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
- case *Transactions:
+ // Wait for the transaction announcements, make sure all txs ar propagated.
+ for time.Now().Before(end) {
+ msg, err := recvConn.ReadEth()
+ if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+ switch msg := msg.(type) {
+ case *eth.TransactionsPacket:
for _, tx := range *msg {
- recvHashes = append(recvHashes, tx.Hash())
+ got[tx.Hash()] = true
}
- case *NewPooledTransactionHashes66:
- recvHashes = append(recvHashes, *msg...)
- case *NewPooledTransactionHashes:
- recvHashes = append(recvHashes, msg.Hashes...)
+ case *eth.NewPooledTransactionHashesPacket:
+ for _, hash := range msg.Hashes {
+ got[hash] = true
+ }
+ case *eth.GetBlockHeadersPacket:
+ headers, err := s.chain.GetHeaders(msg)
+ if err != nil {
+ t.Logf("invalid GetBlockHeaders request: %v", err)
+ }
+ recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{
+ RequestId: msg.RequestId,
+ BlockHeadersRequest: headers,
+ })
default:
- if !strings.Contains(pretty.Sdump(msg), "i/o timeout") {
- return fmt.Errorf("unexpected message while waiting to receive txs: %s", pretty.Sdump(msg))
+ return fmt.Errorf("unexpected eth wire msg: %s", pretty.Sdump(msg))
+ }
+
+ // Check if all txs received.
+ allReceived := func() bool {
+ for _, tx := range txs {
+ if !got[tx.Hash()] {
+ return false
+ }
}
+ return true
}
- // break once all 2000 txs have been received
- if len(recvHashes) == 2000 {
- break
- }
-
- if len(recvHashes) > 0 {
- _, missingTxs := compareReceivedTxs(recvHashes, txs)
- if len(missingTxs) > 0 {
- continue
- } else {
- t.Logf("successfully received all %d txs", len(txs))
- return nil
- }
+ if allReceived() {
+ return nil
}
}
- _, missingTxs := compareReceivedTxs(recvHashes, txs)
- if len(missingTxs) > 0 {
- for _, missing := range missingTxs {
- t.Logf("missing tx: %v", missing.Hash())
- }
-
- return fmt.Errorf("missing %d txs", len(missingTxs))
- }
-
- return nil
+ return fmt.Errorf("timed out waiting for txs")
}
-// checkMaliciousTxPropagation checks whether the given malicious transactions were
-// propagated by the node.
-// nolint:typecheck
-func checkMaliciousTxPropagation(s *Suite, txs []*types.Transaction, conn *Conn) error {
- switch msg := conn.readAndServe(s.chain, time.Second*8).(type) {
- case *Transactions:
- // check to see if any of the failing txs were in the announcement
- recvTxs := make([]common.Hash, len(*msg))
- for i, recvTx := range *msg {
- recvTxs[i] = recvTx.Hash()
- }
-
- badTxs, _ := compareReceivedTxs(recvTxs, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *NewPooledTransactionHashes66:
- badTxs, _ := compareReceivedTxs(*msg, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *NewPooledTransactionHashes:
- badTxs, _ := compareReceivedTxs(msg.Hashes, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *Error:
- // Transaction should not be announced -> wait for timeout
- return nil
- default:
- return fmt.Errorf("unexpected message in sendFailingTx: %s", pretty.Sdump(msg))
- }
-
- return nil
-}
-
-// compareReceivedTxs compares the received set of txs against the given set of txs,
-// returning both the set received txs that were present within the given txs, and
-// the set of txs that were missing from the set of received txs
-func compareReceivedTxs(recvTxs []common.Hash, txs []*types.Transaction) (present []*types.Transaction, missing []*types.Transaction) {
- // create a map of the hashes received from node
- recvHashes := make(map[common.Hash]common.Hash)
- for _, hash := range recvTxs {
- recvHashes[hash] = hash
- }
-
- // collect present txs and missing txs separately
- present = make([]*types.Transaction, 0)
- missing = make([]*types.Transaction, 0)
-
- for _, tx := range txs {
- if _, exists := recvHashes[tx.Hash()]; exists {
- present = append(present, tx)
- } else {
- missing = append(missing, tx)
- }
- }
-
- return present, missing
-}
-
-func unknownTx(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
-
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
-
- txNew := types.NewTransaction(tx.Nonce()+1, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data())
-
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func getNextTxFromChain(s *Suite) *types.Transaction {
- // Get a new transaction
- for _, blocks := range s.fullChain.blocks[s.chain.Len():] {
- txs := blocks.Transactions()
- if txs.Len() != 0 {
- return txs[0]
- }
- }
-
- return nil
-}
-
-func generateTxs(s *Suite, numTxs int) (map[common.Hash]common.Hash, []*types.Transaction, error) {
- txHashMap := make(map[common.Hash]common.Hash, numTxs)
- txs := make([]*types.Transaction, numTxs)
-
- nextTx := getNextTxFromChain(s)
- if nextTx == nil {
- return nil, nil, errors.New("failed to get the next transaction")
- }
-
- gas := nextTx.Gas()
-
- nonce = nonce + 1
- // generate txs
- for i := 0; i < numTxs; i++ {
- tx := generateTx(s.chain.chainConfig, nonce, gas)
- if tx == nil {
- return nil, nil, errors.New("failed to get the next transaction")
- }
-
- txHashMap[tx.Hash()] = tx.Hash()
- txs[i] = tx
- nonce = nonce + 1
- }
-
- return txHashMap, txs, nil
-}
-
-func generateTx(chainConfig *params.ChainConfig, nonce uint64, gas uint64) *types.Transaction {
- var to common.Address
- tx := types.NewTransaction(nonce, to, big.NewInt(1), gas, big.NewInt(1), []byte{})
-
- return signWithFaucet(chainConfig, tx)
-}
-
-func getOldTxFromChain(s *Suite) *types.Transaction {
- for _, blocks := range s.fullChain.blocks[:s.chain.Len()-1] {
- txs := blocks.Transactions()
- if txs.Len() != 0 {
- return txs[0]
- }
- }
-
- return nil
-}
-
-func invalidNonceTx(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
-
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
-
- txNew := types.NewTransaction(tx.Nonce()-2, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data())
-
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeAmount(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
-
- amount := largeNumber(2)
-
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
-
- txNew := types.NewTransaction(tx.Nonce(), to, amount, tx.Gas(), tx.GasPrice(), tx.Data())
-
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeGasPrice(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
-
- gasPrice := largeNumber(2)
-
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
-
- txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), gasPrice, tx.Data())
-
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeData(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
-
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
-
- txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), tx.GasPrice(), largeBuffer(2))
-
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func signWithFaucet(chainConfig *params.ChainConfig, tx *types.Transaction) *types.Transaction {
- signer := types.LatestSigner(chainConfig)
-
- signedTx, err := types.SignTx(tx, signer, faucetKey)
+func (s *Suite) sendInvalidTxs(t *utesting.T, txs []*types.Transaction) error {
+ // Open sending conn.
+ sendConn, err := s.dial()
if err != nil {
- return nil
+ return err
+ }
+ defer sendConn.Close()
+ if err = sendConn.peer(s.chain, nil); err != nil {
+ return fmt.Errorf("peering failed: %v", err)
+ }
+ sendConn.SetDeadline(time.Now().Add(timeout))
+
+ // Open receiving conn.
+ recvConn, err := s.dial()
+ if err != nil {
+ return err
+ }
+ defer recvConn.Close()
+ if err = recvConn.peer(s.chain, nil); err != nil {
+ return fmt.Errorf("peering failed: %v", err)
+ }
+ recvConn.SetDeadline(time.Now().Add(timeout))
+
+ if err = sendConn.Write(ethProto, eth.TransactionsMsg, txs); err != nil {
+ return fmt.Errorf("failed to write message to connection: %w", err)
}
- return signedTx
+ // Make map of invalid txs.
+ invalids := make(map[common.Hash]struct{})
+ for _, tx := range txs {
+ invalids[tx.Hash()] = struct{}{}
+ }
+
+ // Get responses.
+ recvConn.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ msg, err := recvConn.ReadEth()
+ if errors.Is(err, os.ErrDeadlineExceeded) {
+ // Successful if no invalid txs are propagated before timeout.
+ return nil
+ } else if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+
+ switch msg := msg.(type) {
+ case *eth.TransactionsPacket:
+ for _, tx := range txs {
+ if _, ok := invalids[tx.Hash()]; ok {
+ return fmt.Errorf("received bad tx: %s", tx.Hash())
+ }
+ }
+ case *eth.NewPooledTransactionHashesPacket:
+ for _, hash := range msg.Hashes {
+ if _, ok := invalids[hash]; ok {
+ return fmt.Errorf("received bad tx: %s", hash)
+ }
+ }
+ case *eth.GetBlockHeadersPacket:
+ headers, err := s.chain.GetHeaders(msg)
+ if err != nil {
+ t.Logf("invalid GetBlockHeaders request: %v", err)
+ }
+ recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{
+ RequestId: msg.RequestId,
+ BlockHeadersRequest: headers,
+ })
+ default:
+ return fmt.Errorf("unexpected eth message: %v", pretty.Sdump(msg))
+ }
+ }
}
diff --git a/cmd/devp2p/internal/ethtest/types.go b/cmd/devp2p/internal/ethtest/types.go
deleted file mode 100644
index 987ab3ce6f..0000000000
--- a/cmd/devp2p/internal/ethtest/types.go
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "crypto/ecdsa"
- "errors"
- "fmt"
- "time"
-
- "github.com/ethereum/go-ethereum/eth/protocols/eth"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/p2p/rlpx"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-type Message interface {
- Code() int
- ReqID() uint64
-}
-
-type Error struct {
- err error
-}
-
-func (e *Error) Unwrap() error { return e.err }
-func (e *Error) Error() string { return e.err.Error() }
-func (e *Error) String() string { return e.Error() }
-
-func (e *Error) Code() int { return -1 }
-func (e *Error) ReqID() uint64 { return 0 }
-
-func errorf(format string, args ...interface{}) *Error {
- return &Error{fmt.Errorf(format, args...)}
-}
-
-// Hello is the RLP structure of the protocol handshake.
-type Hello struct {
- Version uint64
- Name string
- Caps []p2p.Cap
- ListenPort uint64
- ID []byte // secp256k1 public key
-
- // Ignore additional fields (for forward compatibility).
- Rest []rlp.RawValue `rlp:"tail"`
-}
-
-func (msg Hello) Code() int { return 0x00 }
-func (msg Hello) ReqID() uint64 { return 0 }
-
-// Disconnect is the RLP structure for a disconnect message.
-type Disconnect struct {
- Reason p2p.DiscReason
-}
-
-func (msg Disconnect) Code() int { return 0x01 }
-func (msg Disconnect) ReqID() uint64 { return 0 }
-
-type Ping struct{}
-
-func (msg Ping) Code() int { return 0x02 }
-func (msg Ping) ReqID() uint64 { return 0 }
-
-type Pong struct{}
-
-func (msg Pong) Code() int { return 0x03 }
-func (msg Pong) ReqID() uint64 { return 0 }
-
-// Status is the network packet for the status message for eth/64 and later.
-type Status eth.StatusPacket
-
-func (msg Status) Code() int { return 16 }
-func (msg Status) ReqID() uint64 { return 0 }
-
-// NewBlockHashes is the network packet for the block announcements.
-type NewBlockHashes eth.NewBlockHashesPacket
-
-func (msg NewBlockHashes) Code() int { return 17 }
-func (msg NewBlockHashes) ReqID() uint64 { return 0 }
-
-type Transactions eth.TransactionsPacket
-
-func (msg Transactions) Code() int { return 18 }
-func (msg Transactions) ReqID() uint64 { return 18 }
-
-// GetBlockHeaders represents a block header query.
-type GetBlockHeaders eth.GetBlockHeadersPacket
-
-func (msg GetBlockHeaders) Code() int { return 19 }
-func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
-
-type BlockHeaders eth.BlockHeadersPacket
-
-func (msg BlockHeaders) Code() int { return 20 }
-func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
-
-// GetBlockBodies represents a GetBlockBodies request
-type GetBlockBodies eth.GetBlockBodiesPacket
-
-func (msg GetBlockBodies) Code() int { return 21 }
-func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
-
-// BlockBodies is the network packet for block content distribution.
-type BlockBodies eth.BlockBodiesPacket
-
-func (msg BlockBodies) Code() int { return 22 }
-func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
-
-// NewBlock is the network packet for the block propagation message.
-type NewBlock eth.NewBlockPacket
-
-func (msg NewBlock) Code() int { return 23 }
-func (msg NewBlock) ReqID() uint64 { return 0 }
-
-// NewPooledTransactionHashes66 is the network packet for the tx hash propagation message.
-type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket67
-
-func (msg NewPooledTransactionHashes66) Code() int { return 24 }
-func (msg NewPooledTransactionHashes66) ReqID() uint64 { return 0 }
-
-// NewPooledTransactionHashes is the network packet for the tx hash propagation message.
-type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket68
-
-func (msg NewPooledTransactionHashes) Code() int { return 24 }
-func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
-
-type GetPooledTransactions eth.GetPooledTransactionsPacket
-
-func (msg GetPooledTransactions) Code() int { return 25 }
-func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
-
-type PooledTransactions eth.PooledTransactionsPacket
-
-func (msg PooledTransactions) Code() int { return 26 }
-func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
-
-// Conn represents an individual connection with a peer
-type Conn struct {
- *rlpx.Conn
- ourKey *ecdsa.PrivateKey
- negotiatedProtoVersion uint
- negotiatedSnapProtoVersion uint
- ourHighestProtoVersion uint
- ourHighestSnapProtoVersion uint
- caps []p2p.Cap
-}
-
-// Read reads an eth66 packet from the connection.
-func (c *Conn) Read() Message {
- code, rawData, _, err := c.Conn.Read()
- if err != nil {
- return errorf("could not read from connection: %v", err)
- }
-
- var msg Message
-
- switch int(code) {
- case (Hello{}).Code():
- msg = new(Hello)
- case (Ping{}).Code():
- msg = new(Ping)
- case (Pong{}).Code():
- msg = new(Pong)
- case (Disconnect{}).Code():
- msg = new(Disconnect)
- case (Status{}).Code():
- msg = new(Status)
- case (GetBlockHeaders{}).Code():
- ethMsg := new(eth.GetBlockHeadersPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*GetBlockHeaders)(ethMsg)
- case (BlockHeaders{}).Code():
- ethMsg := new(eth.BlockHeadersPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*BlockHeaders)(ethMsg)
- case (GetBlockBodies{}).Code():
- ethMsg := new(eth.GetBlockBodiesPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*GetBlockBodies)(ethMsg)
- case (BlockBodies{}).Code():
- ethMsg := new(eth.BlockBodiesPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*BlockBodies)(ethMsg)
- case (NewBlock{}).Code():
- msg = new(NewBlock)
- case (NewBlockHashes{}).Code():
- msg = new(NewBlockHashes)
- case (Transactions{}).Code():
- msg = new(Transactions)
- case (NewPooledTransactionHashes66{}).Code():
- // Try decoding to eth68
- ethMsg := new(NewPooledTransactionHashes)
- if err := rlp.DecodeBytes(rawData, ethMsg); err == nil {
- return ethMsg
- }
-
- msg = new(NewPooledTransactionHashes66)
- case (GetPooledTransactions{}.Code()):
- ethMsg := new(eth.GetPooledTransactionsPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*GetPooledTransactions)(ethMsg)
- case (PooledTransactions{}.Code()):
- ethMsg := new(eth.PooledTransactionsPacket)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return (*PooledTransactions)(ethMsg)
- default:
- msg = errorf("invalid message code: %d", code)
- }
-
- if msg != nil {
- if err := rlp.DecodeBytes(rawData, msg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
-
- return msg
- }
-
- return errorf("invalid message: %s", string(rawData))
-}
-
-// Write writes a eth packet to the connection.
-func (c *Conn) Write(msg Message) error {
- payload, err := rlp.EncodeToBytes(msg)
- if err != nil {
- return err
- }
-
- _, err = c.Conn.Write(uint64(msg.Code()), payload)
-
- return err
-}
-
-// ReadSnap reads a snap/1 response with the given id from the connection.
-func (c *Conn) ReadSnap(id uint64) (Message, error) {
- respId := id + 1
- start := time.Now()
-
- for respId != id && time.Since(start) < timeout {
- code, rawData, _, err := c.Conn.Read()
- if err != nil {
- return nil, fmt.Errorf("could not read from connection: %v", err)
- }
-
- var snpMsg interface{}
- switch int(code) {
- case (GetAccountRange{}).Code():
- snpMsg = new(GetAccountRange)
- case (AccountRange{}).Code():
- snpMsg = new(AccountRange)
- case (GetStorageRanges{}).Code():
- snpMsg = new(GetStorageRanges)
- case (StorageRanges{}).Code():
- snpMsg = new(StorageRanges)
- case (GetByteCodes{}).Code():
- snpMsg = new(GetByteCodes)
- case (ByteCodes{}).Code():
- snpMsg = new(ByteCodes)
- case (GetTrieNodes{}).Code():
- snpMsg = new(GetTrieNodes)
- case (TrieNodes{}).Code():
- snpMsg = new(TrieNodes)
- default:
- //return nil, fmt.Errorf("invalid message code: %d", code)
- continue
- }
-
- if err := rlp.DecodeBytes(rawData, snpMsg); err != nil {
- return nil, fmt.Errorf("could not rlp decode message: %v", err)
- }
-
- return snpMsg.(Message), nil
- }
- return nil, errors.New("request timed out")
-}
diff --git a/cmd/devp2p/rlpxcmd.go b/cmd/devp2p/rlpxcmd.go
index 17cc3c1f15..aa7d065818 100644
--- a/cmd/devp2p/rlpxcmd.go
+++ b/cmd/devp2p/rlpxcmd.go
@@ -21,13 +21,13 @@ import (
"fmt"
"net"
- "github.com/urfave/cli/v2"
-
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/rlpx"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/urfave/cli/v2"
)
var (
@@ -47,93 +47,119 @@ var (
}
rlpxEthTestCommand = &cli.Command{
Name: "eth-test",
- Usage: "Runs tests against a node",
- ArgsUsage: " ",
+ Usage: "Runs eth protocol tests against a node",
+ ArgsUsage: "",
Action: rlpxEthTest,
Flags: []cli.Flag{
testPatternFlag,
testTAPFlag,
+ testChainDirFlag,
+ testNodeFlag,
+ testNodeJWTFlag,
+ testNodeEngineFlag,
},
}
rlpxSnapTestCommand = &cli.Command{
Name: "snap-test",
- Usage: "Runs tests against a node",
- ArgsUsage: " ",
+ Usage: "Runs snap protocol tests against a node",
+ ArgsUsage: "",
Action: rlpxSnapTest,
Flags: []cli.Flag{
testPatternFlag,
testTAPFlag,
+ testChainDirFlag,
+ testNodeFlag,
+ testNodeJWTFlag,
+ testNodeEngineFlag,
},
}
)
func rlpxPing(ctx *cli.Context) error {
n := getNodeArg(ctx)
-
fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", n.IP(), n.TCP()))
if err != nil {
return err
}
-
conn := rlpx.NewConn(fd, n.Pubkey())
ourKey, _ := crypto.GenerateKey()
-
_, err = conn.Handshake(ourKey)
if err != nil {
return err
}
-
code, data, _, err := conn.Read()
if err != nil {
return err
}
-
switch code {
case 0:
var h ethtest.Hello
if err := rlp.DecodeBytes(data, &h); err != nil {
return fmt.Errorf("invalid handshake: %v", err)
}
-
fmt.Printf("%+v\n", h)
case 1:
var msg []p2p.DiscReason
if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
return errors.New("invalid disconnect message")
}
-
return fmt.Errorf("received disconnect message: %v", msg[0])
default:
return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code)
}
-
return nil
}
// rlpxEthTest runs the eth protocol test suite.
func rlpxEthTest(ctx *cli.Context) error {
- if ctx.NArg() < 3 {
- exit("missing path to chain.rlp as command-line argument")
- }
-
- suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
+ p := cliTestParams(ctx)
+ suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt)
if err != nil {
exit(err)
}
-
return runTests(ctx, suite.EthTests())
}
// rlpxSnapTest runs the snap protocol test suite.
func rlpxSnapTest(ctx *cli.Context) error {
- if ctx.NArg() < 3 {
- exit("missing path to chain.rlp as command-line argument")
- }
-
- suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
+ p := cliTestParams(ctx)
+ suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt)
if err != nil {
exit(err)
}
-
return runTests(ctx, suite.SnapTests())
}
+
+type testParams struct {
+ node *enode.Node
+ engineAPI string
+ jwt string
+ chainDir string
+}
+
+func cliTestParams(ctx *cli.Context) *testParams {
+ nodeStr := ctx.String(testNodeFlag.Name)
+ if nodeStr == "" {
+ exit(fmt.Errorf("missing -%s", testNodeFlag.Name))
+ }
+ node, err := parseNode(nodeStr)
+ if err != nil {
+ exit(err)
+ }
+ p := testParams{
+ node: node,
+ engineAPI: ctx.String(testNodeEngineFlag.Name),
+ jwt: ctx.String(testNodeJWTFlag.Name),
+ chainDir: ctx.String(testChainDirFlag.Name),
+ }
+ if p.engineAPI == "" {
+ exit(fmt.Errorf("missing -%s", testNodeEngineFlag.Name))
+ }
+ if p.jwt == "" {
+ exit(fmt.Errorf("missing -%s", testNodeJWTFlag.Name))
+ }
+ if p.chainDir == "" {
+ exit(fmt.Errorf("missing -%s", testChainDirFlag.Name))
+ }
+ return &p
+}
diff --git a/cmd/devp2p/runtest.go b/cmd/devp2p/runtest.go
index 287274d319..f7eb0f6e24 100644
--- a/cmd/devp2p/runtest.go
+++ b/cmd/devp2p/runtest.go
@@ -22,29 +22,58 @@ import (
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
+ "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/log"
)
var (
testPatternFlag = &cli.StringFlag{
- Name: "run",
- Usage: "Pattern of test suite(s) to run",
+ Name: "run",
+ Usage: "Pattern of test suite(s) to run",
+ Category: flags.TestingCategory,
}
testTAPFlag = &cli.BoolFlag{
- Name: "tap",
- Usage: "Output TAP",
+ Name: "tap",
+ Usage: "Output test results in TAP format",
+ Category: flags.TestingCategory,
}
+
+ // for eth/snap tests
+ testChainDirFlag = &cli.StringFlag{
+ Name: "chain",
+ Usage: "Test chain directory (required)",
+ Category: flags.TestingCategory,
+ }
+ testNodeFlag = &cli.StringFlag{
+ Name: "node",
+ Usage: "Peer-to-Peer endpoint (ENR) of the test node (required)",
+ Category: flags.TestingCategory,
+ }
+ testNodeJWTFlag = &cli.StringFlag{
+ Name: "jwtsecret",
+ Usage: "JWT secret for the engine API of the test node (required)",
+ Category: flags.TestingCategory,
+ Value: "0x7365637265747365637265747365637265747365637265747365637265747365",
+ }
+ testNodeEngineFlag = &cli.StringFlag{
+ Name: "engineapi",
+ Usage: "Engine API endpoint of the test node (required)",
+ Category: flags.TestingCategory,
+ }
+
// These two are specific to the discovery tests.
testListen1Flag = &cli.StringFlag{
- Name: "listen1",
- Usage: "IP address of the first tester",
- Value: v4test.Listen1,
+ Name: "listen1",
+ Usage: "IP address of the first tester",
+ Value: v4test.Listen1,
+ Category: flags.TestingCategory,
}
testListen2Flag = &cli.StringFlag{
- Name: "listen2",
- Usage: "IP address of the second tester",
- Value: v4test.Listen2,
+ Name: "listen2",
+ Usage: "IP address of the second tester",
+ Value: v4test.Listen2,
+ Category: flags.TestingCategory,
}
)
diff --git a/cmd/era/main.go b/cmd/era/main.go
new file mode 100644
index 0000000000..977a0773d6
--- /dev/null
+++ b/cmd/era/main.go
@@ -0,0 +1,324 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/era"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/internal/flags"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/trie"
+ "github.com/urfave/cli/v2"
+)
+
+var app = flags.NewApp("go-ethereum era tool")
+
+var (
+ dirFlag = &cli.StringFlag{
+ Name: "dir",
+ Usage: "directory storing all relevant era1 files",
+ Value: "eras",
+ }
+ networkFlag = &cli.StringFlag{
+ Name: "network",
+ Usage: "network name associated with era1 files",
+ Value: "mainnet",
+ }
+ eraSizeFlag = &cli.IntFlag{
+ Name: "size",
+ Usage: "number of blocks per era",
+ Value: era.MaxEra1Size,
+ }
+ txsFlag = &cli.BoolFlag{
+ Name: "txs",
+ Usage: "print full transaction values",
+ }
+)
+
+var (
+ blockCommand = &cli.Command{
+ Name: "block",
+ Usage: "get block data",
+ ArgsUsage: "",
+ Action: block,
+ Flags: []cli.Flag{
+ txsFlag,
+ },
+ }
+ infoCommand = &cli.Command{
+ Name: "info",
+ ArgsUsage: "",
+ Usage: "get epoch information",
+ Action: info,
+ }
+ verifyCommand = &cli.Command{
+ Name: "verify",
+ ArgsUsage: "",
+ Usage: "verifies each era1 against expected accumulator root",
+ Action: verify,
+ }
+)
+
+func init() {
+ app.Commands = []*cli.Command{
+ blockCommand,
+ infoCommand,
+ verifyCommand,
+ }
+ app.Flags = []cli.Flag{
+ dirFlag,
+ networkFlag,
+ eraSizeFlag,
+ }
+}
+
+func main() {
+ if err := app.Run(os.Args); err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
+}
+
+// block prints the specified block from an era1 store.
+func block(ctx *cli.Context) error {
+ num, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
+ if err != nil {
+ return fmt.Errorf("invalid block number: %w", err)
+ }
+ e, err := open(ctx, num/uint64(ctx.Int(eraSizeFlag.Name)))
+ if err != nil {
+ return fmt.Errorf("error opening era1: %w", err)
+ }
+ defer e.Close()
+ // Read block with number.
+ block, err := e.GetBlockByNumber(num)
+ if err != nil {
+ return fmt.Errorf("error reading block %d: %w", num, err)
+ }
+ // Convert block to JSON and print.
+ val := ethapi.RPCMarshalBlock(block, ctx.Bool(txsFlag.Name), ctx.Bool(txsFlag.Name), params.MainnetChainConfig, nil)
+ b, err := json.MarshalIndent(val, "", " ")
+ if err != nil {
+ return fmt.Errorf("error marshaling json: %w", err)
+ }
+ fmt.Println(string(b))
+ return nil
+}
+
+// info prints some high-level information about the era1 file.
+func info(ctx *cli.Context) error {
+ epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
+ if err != nil {
+ return fmt.Errorf("invalid epoch number: %w", err)
+ }
+ e, err := open(ctx, epoch)
+ if err != nil {
+ return err
+ }
+ defer e.Close()
+ acc, err := e.Accumulator()
+ if err != nil {
+ return fmt.Errorf("error reading accumulator: %w", err)
+ }
+ td, err := e.InitialTD()
+ if err != nil {
+ return fmt.Errorf("error reading total difficulty: %w", err)
+ }
+ info := struct {
+ Accumulator common.Hash `json:"accumulator"`
+ TotalDifficulty *big.Int `json:"totalDifficulty"`
+ StartBlock uint64 `json:"startBlock"`
+ Count uint64 `json:"count"`
+ }{
+ acc, td, e.Start(), e.Count(),
+ }
+ b, _ := json.MarshalIndent(info, "", " ")
+ fmt.Println(string(b))
+ return nil
+}
+
+// open opens an era1 file at a certain epoch.
+func open(ctx *cli.Context, epoch uint64) (*era.Era, error) {
+ var (
+ dir = ctx.String(dirFlag.Name)
+ network = ctx.String(networkFlag.Name)
+ )
+ entries, err := era.ReadDir(dir, network)
+ if err != nil {
+ return nil, fmt.Errorf("error reading era dir: %w", err)
+ }
+ if epoch >= uint64(len(entries)) {
+ return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
+ }
+ return era.Open(path.Join(dir, entries[epoch]))
+}
+
+// verify checks each era1 file in a directory to ensure it is well-formed and
+// that the accumulator matches the expected value.
+func verify(ctx *cli.Context) error {
+ if ctx.Args().Len() != 1 {
+ return fmt.Errorf("missing accumulators file")
+ }
+
+ roots, err := readHashes(ctx.Args().First())
+ if err != nil {
+ return fmt.Errorf("unable to read expected roots file: %w", err)
+ }
+
+ var (
+ dir = ctx.String(dirFlag.Name)
+ network = ctx.String(networkFlag.Name)
+ start = time.Now()
+ reported = time.Now()
+ )
+
+ entries, err := era.ReadDir(dir, network)
+ if err != nil {
+ return fmt.Errorf("error reading %s: %w", dir, err)
+ }
+
+ if len(entries) != len(roots) {
+ return fmt.Errorf("number of era1 files should match the number of accumulator hashes")
+ }
+
+ // Verify each epoch matches the expected root.
+ for i, want := range roots {
+ // Wrap in function so defers don't stack.
+ err := func() error {
+ name := entries[i]
+ e, err := era.Open(path.Join(dir, name))
+ if err != nil {
+ return fmt.Errorf("error opening era1 file %s: %w", name, err)
+ }
+ defer e.Close()
+ // Read accumulator and check against expected.
+ if got, err := e.Accumulator(); err != nil {
+ return fmt.Errorf("error retrieving accumulator for %s: %w", name, err)
+ } else if got != want {
+ return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want)
+ }
+ // Recompute accumulator.
+ if err := checkAccumulator(e); err != nil {
+ return fmt.Errorf("error verify era1 file %s: %w", name, err)
+ }
+ // Give the user some feedback that something is happening.
+ if time.Since(reported) >= 8*time.Second {
+ fmt.Printf("Verifying Era1 files \t\t verified=%d,\t elapsed=%s\n", i, common.PrettyDuration(time.Since(start)))
+ reported = time.Now()
+ }
+ return nil
+ }()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// checkAccumulator verifies the accumulator matches the data in the Era.
+func checkAccumulator(e *era.Era) error {
+ var (
+ err error
+ want common.Hash
+ td *big.Int
+ tds = make([]*big.Int, 0)
+ hashes = make([]common.Hash, 0)
+ )
+ if want, err = e.Accumulator(); err != nil {
+ return fmt.Errorf("error reading accumulator: %w", err)
+ }
+ if td, err = e.InitialTD(); err != nil {
+ return fmt.Errorf("error reading total difficulty: %w", err)
+ }
+ it, err := era.NewIterator(e)
+ if err != nil {
+ return fmt.Errorf("error making era iterator: %w", err)
+ }
+ // To fully verify an era the following attributes must be checked:
+ // 1) the block index is constructed correctly
+ // 2) the tx root matches the value in the block
+ // 3) the receipts root matches the value in the block
+ // 4) the starting total difficulty value is correct
+ // 5) the accumulator is correct by recomputing it locally, which verifies
+ // the blocks are all correct (via hash)
+ //
+ // The attributes 1), 2), and 3) are checked for each block. 4) and 5) require
+ // accumulation across the entire set and are verified at the end.
+ for it.Next() {
+ // 1) next() walks the block index, so we're able to implicitly verify it.
+ if it.Error() != nil {
+ return fmt.Errorf("error reading block %d: %w", it.Number(), err)
+ }
+ block, receipts, err := it.BlockAndReceipts()
+ if it.Error() != nil {
+ return fmt.Errorf("error reading block %d: %w", it.Number(), err)
+ }
+ // 2) recompute tx root and verify against header.
+ tr := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil))
+ if tr != block.TxHash() {
+ return fmt.Errorf("tx root in block %d mismatch: want %s, got %s", block.NumberU64(), block.TxHash(), tr)
+ }
+ // 3) recompute receipt root and check value against block.
+ rr := types.DeriveSha(receipts, trie.NewStackTrie(nil))
+ if rr != block.ReceiptHash() {
+ return fmt.Errorf("receipt root in block %d mismatch: want %s, got %s", block.NumberU64(), block.ReceiptHash(), rr)
+ }
+ hashes = append(hashes, block.Hash())
+ td.Add(td, block.Difficulty())
+ tds = append(tds, new(big.Int).Set(td))
+ }
+ // 4+5) Verify accumulator and total difficulty.
+ got, err := era.ComputeAccumulator(hashes, tds)
+ if err != nil {
+ return fmt.Errorf("error computing accumulator: %w", err)
+ }
+ if got != want {
+ return fmt.Errorf("expected accumulator root does not match calculated: got %s, want %s", got, want)
+ }
+ return nil
+}
+
+// readHashes reads a file of newline-delimited hashes.
+func readHashes(f string) ([]common.Hash, error) {
+ b, err := os.ReadFile(f)
+ if err != nil {
+ return nil, fmt.Errorf("unable to open accumulators file")
+ }
+ s := strings.Split(string(b), "\n")
+ // Remove empty last element, if present.
+ if s[len(s)-1] == "" {
+ s = s[:len(s)-1]
+ }
+ // Convert to hashes.
+ r := make([]common.Hash, len(s))
+ for i := range s {
+ r[i] = common.HexToHash(s[i])
+ }
+ return r, nil
+}
diff --git a/cmd/evm/README.md b/cmd/evm/README.md
index 41d8ced278..25647c18a9 100644
--- a/cmd/evm/README.md
+++ b/cmd/evm/README.md
@@ -214,7 +214,7 @@ exitcode:3 OK
The chain configuration to be used for a transition is specified via the
`--state.fork` CLI flag. A list of possible values and configurations can be
-found in [`tests/init.go`](tests/init.go).
+found in [`tests/init.go`](../../tests/init.go).
#### Examples
##### Basic usage
diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go
index 9c8f01286e..6ba8869186 100644
--- a/cmd/evm/internal/t8ntool/execution.go
+++ b/cmd/evm/internal/t8ntool/execution.go
@@ -36,13 +36,14 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
-
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
type Prestate struct {
- Env stEnv `json:"env"`
- Pre core.GenesisAlloc `json:"pre"`
+ Env stEnv `json:"env"`
+ Pre types.GenesisAlloc `json:"pre"`
}
// ExecutionResult contains the execution status after running a state test, any
@@ -145,6 +146,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rejectedTxs []*rejectedTx
includedTxs types.Transactions
gasUsed = uint64(0)
+ blobGasUsed = uint64(0)
receipts = make(types.Receipts, 0)
txIndex = 0
)
@@ -195,7 +197,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
}
- var blobGasUsed uint64
for i := 0; txIt.Next(); i++ {
tx, err := txIt.Tx()
@@ -217,15 +218,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
continue
}
+ txBlobGas := uint64(0)
if tx.Type() == types.BlobTxType {
- txBlobGas := uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
+ txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max {
err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
log.Warn("rejected tx", "index", i, "err", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
continue
}
- blobGasUsed += txBlobGas
}
tracer, err := getTracerFn(txIndex, tx.Hash())
if err != nil {
@@ -260,7 +261,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if hashError != nil {
return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
}
-
+ blobGasUsed += txBlobGas
gasUsed += msgResult.UsedGas
// Receipt:
@@ -325,16 +326,16 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
reward.Mul(reward, blockReward)
reward.Div(reward, big.NewInt(8))
- statedb.AddBalance(ommer.Address, reward)
+ statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward))
}
- statedb.AddBalance(pre.Env.Coinbase, minerReward)
+ statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward))
}
// Apply withdrawals
for _, w := range pre.Env.Withdrawals {
// Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
- statedb.AddBalance(w.Address, amount)
+ statedb.AddBalance(w.Address, uint256.MustFromBig(amount))
}
// Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
@@ -373,14 +374,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return statedb, execRs, body, nil
}
-func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
- sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
+func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
+ sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
- statedb.SetBalance(addr, a.Balance)
-
+ statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go
index d1746ecfa9..2a6fb18f5f 100644
--- a/cmd/evm/internal/t8ntool/transition.go
+++ b/cmd/evm/internal/t8ntool/transition.go
@@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
- "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -75,10 +74,10 @@ var (
)
type input struct {
- Alloc core.GenesisAlloc `json:"alloc,omitempty"`
- Env *stEnv `json:"env,omitempty"`
- Txs []*txWithKey `json:"txs,omitempty"`
- TxRlp string `json:"txsRlp,omitempty"`
+ Alloc types.GenesisAlloc `json:"alloc,omitempty"`
+ Env *stEnv `json:"env,omitempty"`
+ Txs []*txWithKey `json:"txs,omitempty"`
+ TxRlp string `json:"txsRlp,omitempty"`
}
func Transition(ctx *cli.Context) error {
@@ -194,7 +193,7 @@ func Transition(ctx *cli.Context) error {
if err != nil {
return err
}
- // Dump the excution result
+ // Dump the execution result
collector := make(Alloc)
s.DumpToCollector(collector, nil)
return dispatchOutput(ctx, baseDir, result, collector, body)
@@ -278,7 +277,7 @@ func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
return nil
}
-type Alloc map[common.Address]core.GenesisAccount
+type Alloc map[common.Address]types.Account
func (g Alloc) OnRoot(common.Hash) {}
@@ -286,7 +285,8 @@ func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
if addr == nil {
return
}
- balance, _ := new(big.Int).SetString(dumpAccount.Balance, 10)
+
+ balance, _ := new(big.Int).SetString(dumpAccount.Balance, 0)
var storage map[common.Hash]common.Hash
if dumpAccount.Storage != nil {
@@ -296,7 +296,7 @@ func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
}
}
- genesisAccount := core.GenesisAccount{
+ genesisAccount := types.Account{
Code: dumpAccount.Code,
Storage: storage,
Balance: balance,
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index df9edfe48b..ed84a0adc8 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -40,8 +40,8 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
)
var runCommand = &cli.Command{
@@ -156,7 +156,7 @@ func runCmd(ctx *cli.Context) error {
}
db := rawdb.NewMemoryDatabase()
- triedb := trie.NewDatabase(db, &trie.Config{
+ triedb := triedb.NewDatabase(db, &triedb.Config{
Preimages: preimages,
HashDB: hashdb.Defaults,
})
diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go
index 61337c6dc4..26be7d902b 100644
--- a/cmd/evm/staterunner.go
+++ b/cmd/evm/staterunner.go
@@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/tests"
@@ -92,27 +91,28 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
return err
}
- var tests map[string]tests.StateTest
- if err := json.Unmarshal(src, &tests); err != nil {
+ var testsByName map[string]tests.StateTest
+ if err := json.Unmarshal(src, &testsByName); err != nil {
return err
}
- // Iterate over all the tests, run them and aggregate the results
- results := make([]StatetestResult, 0, len(tests))
- for key, test := range tests {
+ // Iterate over all the tests, run them and aggregate the results
+ results := make([]StatetestResult, 0, len(testsByName))
+
+ for key, test := range testsByName {
for _, st := range test.Subtests() {
// Run the test and aggregate the result
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
- test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, statedb *state.StateDB) {
+ test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
var root common.Hash
- if statedb != nil {
- root = statedb.IntermediateRoot(false)
+ if tstate.StateDB != nil {
+ root = tstate.StateDB.IntermediateRoot(false)
result.Root = &root
if jsonOut {
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
}
if dump { // Dump any state to aid debugging
- cpy, _ := state.New(root, statedb.Database(), nil)
+ cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
dump := cpy.RawDump(nil)
result.State = &dump
}
diff --git a/cmd/evm/transition-test.sh b/cmd/evm/transition-test.sh
index 8cc6aa41de..2ddda2d473 100644
--- a/cmd/evm/transition-test.sh
+++ b/cmd/evm/transition-test.sh
@@ -103,7 +103,7 @@ type Env struct {
CurrentTimestamp uint64 `json:"currentTimestamp"`
Withdrawals []*Withdrawal `json:"withdrawals"`
// optional
- CurrentDifficulty *big.Int `json:"currentDifficuly"`
+ CurrentDifficulty *big.Int `json:"currentDifficulty"`
CurrentRandom *big.Int `json:"currentRandom"`
CurrentBaseFee *big.Int `json:"currentBaseFee"`
ParentDifficulty *big.Int `json:"parentDifficulty"`
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 307fe59f7f..7d2c5b60f4 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -38,10 +38,12 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/internal/era"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
)
var (
@@ -124,6 +126,33 @@ Optional second and third arguments control the first and
last block to write. In this mode, the file will be appended
if already existing. If the file ends with .gz, the output will
be gzipped.`,
+ }
+ importHistoryCommand = &cli.Command{
+ Action: importHistory,
+ Name: "import-history",
+ Usage: "Import an Era archive",
+ ArgsUsage: "",
+ Flags: flags.Merge([]cli.Flag{
+ utils.TxLookupLimitFlag,
+ },
+ utils.DatabaseFlags,
+ utils.NetworkFlags,
+ ),
+ Description: `
+The import-history command will import blocks and their corresponding receipts
+from Era archives.
+`,
+ }
+ exportHistoryCommand = &cli.Command{
+ Action: exportHistory,
+ Name: "export-history",
+ Usage: "Export blockchain history to Era archives",
+ ArgsUsage: " ",
+ Flags: flags.Merge(utils.DatabaseFlags),
+ Description: `
+The export-history command will export blocks and their corresponding receipts
+into Era archives. Eras are typically packaged in steps of 8192 blocks.
+`,
}
importPreimagesCommand = &cli.Command{
Action: importPreimages,
@@ -391,7 +420,97 @@ func exportChain(ctx *cli.Context) error {
err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last))
}
+ if err != nil {
+ utils.Fatalf("Export error: %v\n", err)
+ }
+ fmt.Printf("Export done in %v\n", time.Since(start))
+ return nil
+}
+func importHistory(ctx *cli.Context) error {
+ if ctx.Args().Len() != 1 {
+ utils.Fatalf("usage: %s", ctx.Command.ArgsUsage)
+ }
+
+ stack, _ := makeConfigNode(ctx)
+ defer stack.Close()
+
+ chain, db := utils.MakeChain(ctx, stack, false)
+ defer db.Close()
+
+ var (
+ start = time.Now()
+ dir = ctx.Args().Get(0)
+ network string
+ )
+
+ // Determine network.
+ if utils.IsNetworkPreset(ctx) {
+ switch {
+ case ctx.Bool(utils.MainnetFlag.Name):
+ network = "mainnet"
+ case ctx.Bool(utils.SepoliaFlag.Name):
+ network = "sepolia"
+ case ctx.Bool(utils.GoerliFlag.Name):
+ network = "goerli"
+ }
+ } else {
+ // No network flag set, try to determine network based on files
+ // present in directory.
+ var networks []string
+ for _, n := range params.NetworkNames {
+ entries, err := era.ReadDir(dir, n)
+ if err != nil {
+ return fmt.Errorf("error reading %s: %w", dir, err)
+ }
+ if len(entries) > 0 {
+ networks = append(networks, n)
+ }
+ }
+ if len(networks) == 0 {
+ return fmt.Errorf("no era1 files found in %s", dir)
+ }
+ if len(networks) > 1 {
+ return fmt.Errorf("multiple networks found, use a network flag to specify desired network")
+ }
+ network = networks[0]
+ }
+
+ if err := utils.ImportHistory(chain, db, dir, network); err != nil {
+ return err
+ }
+ fmt.Printf("Import done in %v\n", time.Since(start))
+ return nil
+}
+
+// exportHistory exports chain history in Era archives at a specified
+// directory.
+func exportHistory(ctx *cli.Context) error {
+ if ctx.Args().Len() != 3 {
+ utils.Fatalf("usage: %s", ctx.Command.ArgsUsage)
+ }
+
+ stack, _ := makeConfigNode(ctx)
+ defer stack.Close()
+
+ chain, _ := utils.MakeChain(ctx, stack, true)
+ start := time.Now()
+
+ var (
+ dir = ctx.Args().Get(0)
+ first, ferr = strconv.ParseInt(ctx.Args().Get(1), 10, 64)
+ last, lerr = strconv.ParseInt(ctx.Args().Get(2), 10, 64)
+ )
+ if ferr != nil || lerr != nil {
+ utils.Fatalf("Export error in parsing parameters: block number not an integer\n")
+ }
+ if first < 0 || last < 0 {
+ utils.Fatalf("Export error: block number must be greater than 0\n")
+ }
+ if head := chain.CurrentSnapBlock(); uint64(last) > head.Number.Uint64() {
+ utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.Number.Uint64())
+ }
+ err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxEra1Size))
if err != nil {
utils.Fatalf("Export error: %v\n", err)
}
diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index 2485f87b63..4e20b8d387 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -43,12 +43,22 @@ import (
)
var (
+ removeStateDataFlag = &cli.BoolFlag{
+ Name: "remove.state",
+ Usage: "If set, selects the state data for removal",
+ }
+ removeChainDataFlag = &cli.BoolFlag{
+ Name: "remove.chain",
+ Usage: "If set, selects the state data for removal",
+ }
+
removedbCommand = &cli.Command{
Action: removeDB,
Name: "removedb",
Usage: "Remove blockchain and state databases",
ArgsUsage: "",
- Flags: utils.DatabaseFlags,
+ Flags: flags.Merge(utils.DatabaseFlags,
+ []cli.Flag{removeStateDataFlag, removeChainDataFlag}),
Description: `
Remove blockchain and state databases`,
}
@@ -198,66 +208,85 @@ WARNING: This is a low-level operation which may cause database corruption!`,
func removeDB(ctx *cli.Context) error {
stack, config := makeConfigNode(ctx)
- // Remove the full node state database
- path := stack.ResolvePath("chaindata")
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "full node state database")
- } else {
- log.Info("Full node state database missing", "path", path)
- }
- // Remove the full node ancient database
- path = config.Eth.DatabaseFreezer
-
+ // Resolve folder paths.
+ var (
+ rootDir = stack.ResolvePath("chaindata")
+ ancientDir = config.Eth.DatabaseFreezer
+ )
switch {
- case path == "":
- path = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
- case !filepath.IsAbs(path):
- path = config.Node.ResolvePath(path)
- }
-
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "full node ancient database")
- } else {
- log.Info("Full node ancient database missing", "path", path)
- }
- // Remove the light node database
- path = stack.ResolvePath("lightchaindata")
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "light node database")
- } else {
- log.Info("Light node database missing", "path", path)
+ case ancientDir == "":
+ ancientDir = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
+ case !filepath.IsAbs(ancientDir):
+ ancientDir = config.Node.ResolvePath(ancientDir)
}
+ // Delete state data
+ statePaths := []string{rootDir, filepath.Join(ancientDir, rawdb.StateFreezerName)}
+ confirmAndRemoveDB(statePaths, "state data", ctx, removeStateDataFlag.Name)
+ // Delete ancient chain
+ chainPaths := []string{filepath.Join(ancientDir, rawdb.ChainFreezerName)}
+ confirmAndRemoveDB(chainPaths, "ancient chain", ctx, removeChainDataFlag.Name)
return nil
}
-// confirmAndRemoveDB prompts the user for a last confirmation and removes the
-// folder if accepted.
-func confirmAndRemoveDB(database string, kind string) {
- confirm, err := prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database))
+// removeFolder deletes all files (not folders) inside the directory 'dir' (but
+// not files in subfolders).
+func removeFolder(dir string) {
+ filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ // If we're at the top level folder, recurse into
+ if path == dir {
+ return nil
+ }
+ // Delete all the files, but not subfolders
+ if !info.IsDir() {
+ os.Remove(path)
+ return nil
+ }
+ return filepath.SkipDir
+ })
+}
+// confirmAndRemoveDB prompts the user for a last confirmation and removes the
+// list of folders if accepted.
+func confirmAndRemoveDB(paths []string, kind string, ctx *cli.Context, removeFlagName string) {
+ var (
+ confirm bool
+ err error
+ )
+ msg := fmt.Sprintf("Location(s) of '%s': \n", kind)
+ for _, path := range paths {
+ msg += fmt.Sprintf("\t- %s\n", path)
+ }
+ fmt.Println(msg)
+ if ctx.IsSet(removeFlagName) {
+ confirm = ctx.Bool(removeFlagName)
+ if confirm {
+ fmt.Printf("Remove '%s'? [y/n] y\n", kind)
+ } else {
+ fmt.Printf("Remove '%s'? [y/n] n\n", kind)
+ }
+ } else {
+ confirm, err = prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove '%s'?", kind))
+ }
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
- log.Info("Database deletion skipped", "path", database)
+ log.Info("Database deletion skipped", "kind", kind, "paths", paths)
default:
- start := time.Now()
-
- filepath.Walk(database, func(path string, info os.FileInfo, err error) error {
- // If we're at the top level folder, recurse into
- if path == database {
- return nil
+ var (
+ deleted []string
+ start = time.Now()
+ )
+ for _, path := range paths {
+ if common.FileExist(path) {
+ removeFolder(path)
+ deleted = append(deleted, path)
+ } else {
+ log.Info("Folder is not existent", "path", path)
}
- // Delete all the files, but not subfolders
- if !info.IsDir() {
- os.Remove(path)
- return nil
- }
-
- return filepath.SkipDir
- })
- log.Info("Database successfully deleted", "path", database, "elapsed", common.PrettyDuration(time.Since(start)))
+ }
+ log.Info("Database successfully deleted", "kind", kind, "paths", deleted, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
diff --git a/cmd/geth/logtestcmd_active.go b/cmd/geth/logtestcmd_active.go
index 5cce1ec6ab..f2a2c5ded5 100644
--- a/cmd/geth/logtestcmd_active.go
+++ b/cmd/geth/logtestcmd_active.go
@@ -26,7 +26,6 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
"github.com/urfave/cli/v2"
@@ -51,9 +50,6 @@ func (c customQuotedStringer) String() string {
// logTest is an entry point which spits out some logs. This is used by testing
// to verify expected outputs
func logTest(ctx *cli.Context) error {
- // clear field padding map
- debug.ResetLogging()
-
{ // big.Int
ba, _ := new(big.Int).SetString("111222333444555678999", 10) // "111,222,333,444,555,678,999"
bb, _ := new(big.Int).SetString("-111222333444555678999", 10) // "-111,222,333,444,555,678,999"
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index dc9fe67742..158f8f43d1 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-// geth is the official command-line client for Ethereum.
+// geth is a command-line client for Ethereum.
package main
import (
@@ -214,12 +214,13 @@ var app = flags.NewApp("the go-ethereum command line interface")
func init() {
// Initialize the CLI app and start Geth
app.Action = geth
- app.Copyright = "Copyright 2013-2023 The go-ethereum Authors"
app.Commands = []*cli.Command{
// See chaincmd.go:
initCommand,
importCommand,
exportCommand,
+ importHistoryCommand,
+ exportHistoryCommand,
importPreimagesCommand,
removedbCommand,
dumpCommand,
diff --git a/cmd/geth/testdata/logging/logtest-json.txt b/cmd/geth/testdata/logging/logtest-json.txt
index 3bfe718660..d2bd0ad91a 100644
--- a/cmd/geth/testdata/logging/logtest-json.txt
+++ b/cmd/geth/testdata/logging/logtest-json.txt
@@ -29,7 +29,7 @@
{"t":"2023-11-22T15:42:00.408237+08:00","lvl":"info","msg":"repeated-key 2","xx":"short","xx":"longer"}
{"t":"2023-11-22T15:42:00.408241+08:00","lvl":"info","msg":"log at level info"}
{"t":"2023-11-22T15:42:00.408244+08:00","lvl":"warn","msg":"log at level warn"}
-{"t":"2023-11-22T15:42:00.408247+08:00","lvl":"eror","msg":"log at level error"}
+{"t":"2023-11-22T15:42:00.408247+08:00","lvl":"error","msg":"log at level error"}
{"t":"2023-11-22T15:42:00.408251+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned left"}
{"t":"2023-11-22T15:42:00.408254+08:00","lvl":"info","msg":"test","bar":"a long message","a":1}
{"t":"2023-11-22T15:42:00.408258+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned right"}
diff --git a/cmd/geth/testdata/logging/logtest-logfmt.txt b/cmd/geth/testdata/logging/logtest-logfmt.txt
index f20d66635d..5c5316b7d9 100644
--- a/cmd/geth/testdata/logging/logtest-logfmt.txt
+++ b/cmd/geth/testdata/logging/logtest-logfmt.txt
@@ -29,7 +29,7 @@ t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 1" foo=alpha foo=beta
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 2" xx=short xx=longer
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="log at level info"
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=warn msg="log at level warn"
-t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=eror msg="log at level error"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=error msg="log at level error"
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned left"
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar="a long message" a=1
t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned right"
diff --git a/cmd/rlpdump/main.go b/cmd/rlpdump/main.go
index c1b6c86147..9c9780c5c9 100644
--- a/cmd/rlpdump/main.go
+++ b/cmd/rlpdump/main.go
@@ -25,7 +25,9 @@ import (
"flag"
"fmt"
"io"
+ "math"
"os"
+ "strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
@@ -37,6 +39,7 @@ var (
reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp")
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
single = flag.Bool("single", false, "print only the first element, discard the rest")
+ showpos = flag.Bool("pos", false, "display element byte posititions")
)
func init() {
@@ -52,8 +55,7 @@ If the filename is omitted, data is read from stdin.`)
func main() {
flag.Parse()
- var r io.Reader
-
+ var r *inStream
switch {
case *hexMode != "":
data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x"))
@@ -61,10 +63,10 @@ func main() {
die(err)
}
- r = bytes.NewReader(data)
+ r = newInStream(bytes.NewReader(data), int64(len(data)))
case flag.NArg() == 0:
- r = os.Stdin
+ r = newInStream(bufio.NewReader(os.Stdin), 0)
case flag.NArg() == 1:
fd, err := os.Open(flag.Arg(0))
@@ -73,7 +75,12 @@ func main() {
}
defer fd.Close()
- r = fd
+ var size int64
+ finfo, err := fd.Stat()
+ if err == nil {
+ size = finfo.Size()
+ }
+ r = newInStream(bufio.NewReader(fd), size)
default:
fmt.Fprintln(os.Stderr, "Error: too many arguments")
@@ -100,11 +107,11 @@ func main() {
}
}
-func rlpToText(r io.Reader, out io.Writer) error {
- s := rlp.NewStream(r, 0)
+func rlpToText(in *inStream, out io.Writer) error {
+ stream := rlp.NewStream(in, 0)
for {
- if err := dump(s, 0, out); err != nil {
+ if err := dump(in, stream, 0, out); err != nil {
if err != io.EOF {
return err
}
@@ -122,7 +129,10 @@ func rlpToText(r io.Reader, out io.Writer) error {
return nil
}
-func dump(s *rlp.Stream, depth int, out io.Writer) error {
+func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error {
+ if *showpos {
+ fmt.Fprintf(out, "%s: ", in.posLabel())
+ }
kind, size, err := s.Kind()
if err != nil {
return err
@@ -153,8 +163,7 @@ func dump(s *rlp.Stream, depth int, out io.Writer) error {
if i > 0 {
fmt.Fprint(out, ",\n")
}
-
- if err := dump(s, depth+1, out); err == rlp.EOL {
+ if err := dump(in, s, depth+1, out); err == rlp.EOL {
break
} else if err != nil {
return err
@@ -233,3 +242,36 @@ func textToRlp(r io.Reader) ([]byte, error) {
return data, err
}
+
+type inStream struct {
+ br rlp.ByteReader
+ pos int
+ columns int
+}
+
+func newInStream(br rlp.ByteReader, totalSize int64) *inStream {
+ col := int(math.Ceil(math.Log10(float64(totalSize))))
+ return &inStream{br: br, columns: col}
+}
+
+func (rc *inStream) Read(b []byte) (n int, err error) {
+ n, err = rc.br.Read(b)
+ rc.pos += n
+ return n, err
+}
+
+func (rc *inStream) ReadByte() (byte, error) {
+ b, err := rc.br.ReadByte()
+ if err == nil {
+ rc.pos++
+ }
+ return b, err
+}
+
+func (rc *inStream) posLabel() string {
+ l := strconv.FormatInt(int64(rc.pos), 10)
+ if len(l) < rc.columns {
+ l = strings.Repeat(" ", rc.columns-len(l)) + l
+ }
+ return l
+}
diff --git a/cmd/rlpdump/rlpdump_test.go b/cmd/rlpdump/rlpdump_test.go
index c3c80e5e55..b2b75abe5c 100644
--- a/cmd/rlpdump/rlpdump_test.go
+++ b/cmd/rlpdump/rlpdump_test.go
@@ -35,7 +35,8 @@ func TestRoundtrip(t *testing.T) {
} {
var out strings.Builder
- err := rlpToText(bytes.NewReader(common.FromHex(want)), &out)
+ in := newInStream(bytes.NewReader(common.FromHex(want)), 0)
+ err := rlpToText(in, &out)
if err != nil {
t.Fatal(err)
}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index e4fab05113..0043799442 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -19,12 +19,15 @@ package utils
import (
"bufio"
+ "bytes"
"compress/gzip"
+ "crypto/sha256"
"errors"
"fmt"
"io"
"os"
"os/signal"
+ "path"
"runtime"
"strings"
"syscall"
@@ -41,8 +44,10 @@ import (
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/debug"
+ "github.com/ethereum/go-ethereum/internal/era"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -251,6 +256,105 @@ func ImportChain(chain *core.BlockChain, fn string) error {
return nil
}
+func readList(filename string) ([]string, error) {
+ b, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ return strings.Split(string(b), "\n"), nil
+}
+
+// ImportHistory imports Era1 files containing historical block information,
+// starting from genesis.
+func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, network string) error {
+ if chain.CurrentSnapBlock().Number.BitLen() != 0 {
+ return fmt.Errorf("history import only supported when starting from genesis")
+ }
+ entries, err := era.ReadDir(dir, network)
+ if err != nil {
+ return fmt.Errorf("error reading %s: %w", dir, err)
+ }
+ checksums, err := readList(path.Join(dir, "checksums.txt"))
+ if err != nil {
+ return fmt.Errorf("unable to read checksums.txt: %w", err)
+ }
+ if len(checksums) != len(entries) {
+ return fmt.Errorf("expected equal number of checksums and entries, have: %d checksums, %d entries", len(checksums), len(entries))
+ }
+ var (
+ start = time.Now()
+ reported = time.Now()
+ imported = 0
+ forker = core.NewForkChoice(chain, nil, nil)
+ h = sha256.New()
+ buf = bytes.NewBuffer(nil)
+ )
+ for i, filename := range entries {
+ err := func() error {
+ f, err := os.Open(path.Join(dir, filename))
+ if err != nil {
+ return fmt.Errorf("unable to open era: %w", err)
+ }
+ defer f.Close()
+
+ // Validate checksum.
+ if _, err := io.Copy(h, f); err != nil {
+ return fmt.Errorf("unable to recalculate checksum: %w", err)
+ }
+ if have, want := common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex(), checksums[i]; have != want {
+ return fmt.Errorf("checksum mismatch: have %s, want %s", have, want)
+ }
+ h.Reset()
+ buf.Reset()
+
+ // Import all block data from Era1.
+ e, err := era.From(f)
+ if err != nil {
+ return fmt.Errorf("error opening era: %w", err)
+ }
+ it, err := era.NewIterator(e)
+ if err != nil {
+ return fmt.Errorf("error making era reader: %w", err)
+ }
+ for it.Next() {
+ block, err := it.Block()
+ if err != nil {
+ return fmt.Errorf("error reading block %d: %w", it.Number(), err)
+ }
+ if block.Number().BitLen() == 0 {
+ continue // skip genesis
+ }
+ receipts, err := it.Receipts()
+ if err != nil {
+ return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
+ }
+ if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start, forker); err != nil {
+ return fmt.Errorf("error inserting header %d: %w", it.Number(), err)
+ } else if status != core.CanonStatTy {
+ return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status)
+ }
+ if _, err := chain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{receipts}, 2^64-1); err != nil {
+ return fmt.Errorf("error inserting body %d: %w", it.Number(), err)
+ }
+ imported += 1
+
+ // Give the user some feedback that something is happening.
+ if time.Since(reported) >= 8*time.Second {
+ log.Info("Importing Era files", "head", it.Number(), "imported", imported, "elapsed", common.PrettyDuration(time.Since(start)))
+ imported = 0
+ reported = time.Now()
+ }
+ }
+ return nil
+ }()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block {
head := chain.CurrentBlock()
for i, block := range blocks {
@@ -325,6 +429,93 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
return nil
}
+// ExportHistory exports blockchain history into the specified directory,
+// following the Era format.
+func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) error {
+ log.Info("Exporting blockchain history", "dir", dir)
+ if head := bc.CurrentBlock().Number.Uint64(); head < last {
+ log.Warn("Last block beyond head, setting last = head", "head", head, "last", last)
+ last = head
+ }
+ network := "unknown"
+ if name, ok := params.NetworkNames[bc.Config().ChainID.String()]; ok {
+ network = name
+ }
+ if err := os.MkdirAll(dir, os.ModePerm); err != nil {
+ return fmt.Errorf("error creating output directory: %w", err)
+ }
+ var (
+ start = time.Now()
+ reported = time.Now()
+ h = sha256.New()
+ buf = bytes.NewBuffer(nil)
+ checksums []string
+ )
+ for i := first; i <= last; i += step {
+ err := func() error {
+ filename := path.Join(dir, era.Filename(network, int(i/step), common.Hash{}))
+ f, err := os.Create(filename)
+ if err != nil {
+ return fmt.Errorf("could not create era file: %w", err)
+ }
+ defer f.Close()
+
+ w := era.NewBuilder(f)
+ for j := uint64(0); j < step && j <= last-i; j++ {
+ var (
+ n = i + j
+ block = bc.GetBlockByNumber(n)
+ )
+ if block == nil {
+ return fmt.Errorf("export failed on #%d: not found", n)
+ }
+ receipts := bc.GetReceiptsByHash(block.Hash())
+ if receipts == nil {
+ return fmt.Errorf("export failed on #%d: receipts not found", n)
+ }
+ td := bc.GetTd(block.Hash(), block.NumberU64())
+ if td == nil {
+ return fmt.Errorf("export failed on #%d: total difficulty not found", n)
+ }
+ if err := w.Add(block, receipts, td); err != nil {
+ return err
+ }
+ }
+ root, err := w.Finalize()
+ if err != nil {
+ return fmt.Errorf("export failed to finalize %d: %w", step/i, err)
+ }
+ // Set correct filename with root.
+ os.Rename(filename, path.Join(dir, era.Filename(network, int(i/step), root)))
+
+ // Compute checksum of entire Era1.
+ if _, err := f.Seek(0, io.SeekStart); err != nil {
+ return err
+ }
+ if _, err := io.Copy(h, f); err != nil {
+ return fmt.Errorf("unable to calculate checksum: %w", err)
+ }
+ checksums = append(checksums, common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex())
+ h.Reset()
+ buf.Reset()
+ return nil
+ }()
+ if err != nil {
+ return err
+ }
+ if time.Since(reported) >= 8*time.Second {
+ log.Info("Exporting blocks", "exported", i, "elapsed", common.PrettyDuration(time.Since(start)))
+ reported = time.Now()
+ }
+ }
+
+ os.WriteFile(path.Join(dir, "checksums.txt"), []byte(strings.Join(checksums, "\n")), os.ModePerm)
+
+ log.Info("Exported blockchain to", "dir", dir)
+
+ return nil
+}
+
// ImportPreimages imports a batch of exported hash preimages into the database.
// It's a part of the deprecated functionality, should be removed in the future.
func ImportPreimages(db ethdb.Database, fn string) error {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index f65940f297..6c0edd3821 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -73,9 +73,9 @@ import (
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// These are all the command line flags we support.
@@ -2310,8 +2310,8 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
}
// MakeTrieDatabase constructs a trie database based on the configured scheme.
-func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *trie.Database {
- config := &trie.Config{
+func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
+ config := &triedb.Config{
Preimages: preimage,
IsVerkle: isVerkle,
}
@@ -2324,12 +2324,12 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
// ignore the parameter silently. TODO(rjl493456442)
// please config it if read mode is implemented.
config.HashDB = hashdb.Defaults
- return trie.NewDatabase(disk, config)
+ return triedb.NewDatabase(disk, config)
}
if readOnly {
config.PathDB = pathdb.ReadOnly
} else {
config.PathDB = pathdb.Defaults
}
- return trie.NewDatabase(disk, config)
+ return triedb.NewDatabase(disk, config)
}
diff --git a/cmd/utils/history_test.go b/cmd/utils/history_test.go
new file mode 100644
index 0000000000..738330daaa
--- /dev/null
+++ b/cmd/utils/history_test.go
@@ -0,0 +1,185 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package utils
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "io"
+ "math/big"
+ "os"
+ "path"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "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/internal/era"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
+)
+
+var (
+ count uint64 = 128
+ step uint64 = 16
+)
+
+func TestHistoryImportAndExport(t *testing.T) {
+ var (
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ address = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.TestChainConfig,
+ Alloc: types.GenesisAlloc{address: {Balance: big.NewInt(1000000000000000000)}},
+ }
+ signer = types.LatestSigner(genesis.Config)
+ )
+
+ // Generate chain.
+ db, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), int(count), func(i int, g *core.BlockGen) {
+ if i == 0 {
+ return
+ }
+ tx, err := types.SignNewTx(key, signer, &types.DynamicFeeTx{
+ ChainID: genesis.Config.ChainID,
+ Nonce: uint64(i - 1),
+ GasTipCap: common.Big0,
+ GasFeeCap: g.PrevBlock(0).BaseFee(),
+ Gas: 50000,
+ To: &common.Address{0xaa},
+ Value: big.NewInt(int64(i)),
+ Data: nil,
+ AccessList: nil,
+ })
+ if err != nil {
+ t.Fatalf("error creating tx: %v", err)
+ }
+ g.AddTx(tx)
+ })
+
+ // Initialize BlockChain.
+ chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
+ if err != nil {
+ t.Fatalf("unable to initialize chain: %v", err)
+ }
+ if _, err := chain.InsertChain(blocks); err != nil {
+ t.Fatalf("error insterting chain: %v", err)
+ }
+
+ // 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)
+
+ // Export history to temp directory.
+ if err := ExportHistory(chain, dir, 0, count, step); err != nil {
+ t.Fatalf("error exporting history: %v", err)
+ }
+
+ // Read checksums.
+ b, err := os.ReadFile(path.Join(dir, "checksums.txt"))
+ if err != nil {
+ t.Fatalf("failed to read checksums: %v", err)
+ }
+ checksums := strings.Split(string(b), "\n")
+
+ // Verify each Era.
+ entries, _ := era.ReadDir(dir, "mainnet")
+ for i, filename := range entries {
+ func() {
+ f, err := os.Open(path.Join(dir, filename))
+ if err != nil {
+ t.Fatalf("error opening era file: %v", err)
+ }
+ var (
+ h = sha256.New()
+ buf = bytes.NewBuffer(nil)
+ )
+ if _, err := io.Copy(h, f); err != nil {
+ t.Fatalf("unable to recalculate checksum: %v", err)
+ }
+ if got, want := common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex(), checksums[i]; got != want {
+ t.Fatalf("checksum %d does not match: got %s, want %s", i, got, want)
+ }
+ e, err := era.From(f)
+ if err != nil {
+ t.Fatalf("error opening era: %v", err)
+ }
+ defer e.Close()
+ it, err := era.NewIterator(e)
+ if err != nil {
+ t.Fatalf("error making era reader: %v", err)
+ }
+ for j := 0; it.Next(); j++ {
+ n := i*int(step) + j
+ if it.Error() != nil {
+ t.Fatalf("error reading block entry %d: %v", n, it.Error())
+ }
+ block, receipts, err := it.BlockAndReceipts()
+ if err != nil {
+ t.Fatalf("error reading block entry %d: %v", n, err)
+ }
+ want := chain.GetBlockByNumber(uint64(n))
+ if want, got := uint64(n), block.NumberU64(); want != got {
+ t.Fatalf("blocks out of order: want %d, got %d", want, got)
+ }
+ if want.Hash() != block.Hash() {
+ t.Fatalf("block hash mismatch %d: want %s, got %s", n, want.Hash().Hex(), block.Hash().Hex())
+ }
+ if got := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); got != want.TxHash() {
+ t.Fatalf("tx hash %d mismatch: want %s, got %s", n, want.TxHash(), got)
+ }
+ if got := types.CalcUncleHash(block.Uncles()); got != want.UncleHash() {
+ t.Fatalf("uncle hash %d mismatch: want %s, got %s", n, want.UncleHash(), got)
+ }
+ if got := types.DeriveSha(receipts, trie.NewStackTrie(nil)); got != want.ReceiptHash() {
+ t.Fatalf("receipt root %d mismatch: want %s, got %s", n, want.ReceiptHash(), got)
+ }
+ }
+ }()
+ }
+
+ // Now import Era.
+ freezer := t.TempDir()
+ db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false, false, false)
+ if err != nil {
+ panic(err)
+ }
+ t.Cleanup(func() {
+ db2.Close()
+ })
+
+ genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
+ imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
+ if err != nil {
+ t.Fatalf("unable to initialize chain: %v", err)
+ }
+ if err := ImportHistory(imported, db2, dir, "mainnet"); err != nil {
+ t.Fatalf("failed to import chain: %v", err)
+ }
+ if have, want := imported.CurrentHeader(), chain.CurrentHeader(); have.Hash() != want.Hash() {
+ t.Fatalf("imported chain does not match expected, have (%d, %s) want (%d, %s)", have.Number, have.Hash(), want.Number, want.Hash())
+ }
+}
diff --git a/common/big.go b/common/big.go
index 65d4377bf7..cbb562a28e 100644
--- a/common/big.go
+++ b/common/big.go
@@ -16,7 +16,11 @@
package common
-import "math/big"
+import (
+ "math/big"
+
+ "github.com/holiman/uint256"
+)
// Common big integers often used
var (
@@ -27,4 +31,6 @@ var (
Big32 = big.NewInt(32)
Big256 = big.NewInt(256)
Big257 = big.NewInt(257)
+
+ U2560 = uint256.NewInt(0)
)
diff --git a/common/math/big.go b/common/math/big.go
index 1c4da384a8..a575d949c9 100644
--- a/common/math/big.go
+++ b/common/math/big.go
@@ -197,6 +197,10 @@ func BigMinUint256(x, y *uint256.Int) *uint256.Int {
return x
}
+func BigIntToUint256Int(x *big.Int) *uint256.Int {
+ return new(uint256.Int).SetUint64(x.Uint64())
+}
+
// FirstBitSet returns the index of the first 1 bit in v, counting from LSB.
func FirstBitSet(v *big.Int) int {
for i := 0; i < v.BitLen(); i++ {
diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
index 9e80066f83..44f343b28c 100644
--- a/consensus/beacon/consensus.go
+++ b/consensus/beacon/consensus.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// Proof-of-stake protocol constants.
@@ -356,8 +357,8 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// Withdrawals processing.
for _, w := range withdrawals {
// Convert amount from gwei to wei.
- amount := new(big.Int).SetUint64(w.Amount)
- amount = amount.Mul(amount, big.NewInt(params.GWei))
+ amount := new(uint256.Int).SetUint64(w.Amount)
+ amount = amount.Mul(amount, uint256.NewInt(params.GWei))
state.AddBalance(w.Address, amount)
}
// No block reward which is issued by consensus layer instead.
diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go
index 0314cef8af..de19bfb7ff 100644
--- a/consensus/bor/bor.go
+++ b/consensus/bor/bor.go
@@ -16,6 +16,7 @@ import (
"time"
lru "github.com/hashicorp/golang-lru"
+ "github.com/holiman/uint256"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"golang.org/x/crypto/sha3"
@@ -884,8 +885,8 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State
log.Info("change contract code", "address", addr)
state.SetCode(addr, account.Code)
- if state.GetBalance(addr).Cmp(big.NewInt(0)) == 0 {
- state.SetBalance(addr, account.Balance)
+ if state.GetBalance(addr).Cmp(uint256.NewInt(0)) == 0 {
+ state.SetBalance(addr, uint256.NewInt(account.Balance.Uint64()))
}
}
}
diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go
index 9713ce7516..f02c03c82b 100644
--- a/consensus/bor/bor_test.go
+++ b/consensus/bor/bor_test.go
@@ -14,7 +14,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func TestGenesisContractChange(t *testing.T) {
@@ -63,7 +63,7 @@ func TestGenesisContractChange(t *testing.T) {
db := rawdb.NewMemoryDatabase()
- genesis := genspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := genspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
statedb, err := state.New(genesis.Root(), state.NewDatabase(db), nil)
require.NoError(t, err)
diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go
index 73516c3c24..88f4ade709 100644
--- a/consensus/bor/statefull/processor.go
+++ b/consensus/bor/statefull/processor.go
@@ -15,6 +15,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
@@ -85,7 +86,7 @@ func ApplyMessage(
*msg.To(),
msg.Data(),
msg.Gas(),
- msg.Value(),
+ uint256.NewInt(msg.Value().Uint64()),
nil,
)
@@ -118,7 +119,7 @@ func ApplyBorMessage(vmenv *vm.EVM, msg Callmsg) (*core.ExecutionResult, error)
*msg.To(),
msg.Data(),
msg.Gas(),
- msg.Value(),
+ uint256.NewInt(msg.Value().Uint64()),
nil,
)
// Update the state with pending changes
diff --git a/consensus/clique/clique_test.go b/consensus/clique/clique_test.go
index c6fe18b60d..7203f8857b 100644
--- a/consensus/clique/clique_test.go
+++ b/consensus/clique/clique_test.go
@@ -48,7 +48,7 @@ func TestReimportMirroredState(t *testing.T) {
genspec := &core.Genesis{
Config: params.AllCliqueProtocolChanges,
ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal),
- Alloc: map[common.Address]core.GenesisAccount{
+ Alloc: map[common.Address]types.Account{
addr: {Balance: big.NewInt(10000000000000000)},
},
BaseFee: big.NewInt(params.InitialBaseFee),
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index ded39d1a09..bd1fca8e51 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -34,16 +34,17 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
// Ethash proof-of-work protocol constants.
var (
- FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
- ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
- ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
- maxUncles = 2 // Maximum number of uncles allowed in a single block
- allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
+ FrontierBlockReward = uint256.NewInt(5e+18) // Block reward in wei for successfully mining a block
+ ByzantiumBlockReward = uint256.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
+ ConstantinopleBlockReward = uint256.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
+ maxUncles = 2 // Maximum number of uncles allowed in a single block
+ allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
// calcDifficultyEip5133 is the difficulty adjustment algorithm as specified by EIP 5133.
// It offsets the bomb a total of 11.4M blocks.
@@ -564,8 +565,8 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
// Some weird constants to avoid constant memory allocs for them.
var (
- big8 = big.NewInt(8)
- big32 = big.NewInt(32)
+ u256_8 = uint256.NewInt(8)
+ u256_32 = uint256.NewInt(32)
)
// AccumulateRewards credits the coinbase of the given block with the mining
@@ -581,16 +582,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
blockReward = ConstantinopleBlockReward
}
// Accumulate the rewards for the miner and any included uncles
- reward := new(big.Int).Set(blockReward)
- r := new(big.Int)
+ reward := new(uint256.Int).Set(blockReward)
+ r := new(uint256.Int)
+ hNum, _ := uint256.FromBig(header.Number)
for _, uncle := range uncles {
- r.Add(uncle.Number, big8)
- r.Sub(r, header.Number)
+ uNum, _ := uint256.FromBig(uncle.Number)
+ r.AddUint64(uNum, 8)
+ r.Sub(r, hNum)
r.Mul(r, blockReward)
- r.Div(r, big8)
+ r.Div(r, u256_8)
state.AddBalance(uncle.Coinbase, r)
- r.Div(blockReward, big32)
+ r.Div(blockReward, u256_32)
reward.Add(reward, r)
}
state.AddBalance(header.Coinbase, reward)
diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go
index 96995616de..e21a44f63d 100644
--- a/consensus/misc/dao.go
+++ b/consensus/misc/dao.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var (
@@ -81,6 +82,6 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr))
- statedb.SetBalance(addr, new(big.Int))
+ statedb.SetBalance(addr, new(uint256.Int))
}
}
diff --git a/core/bench_test.go b/core/bench_test.go
index a5ae3d0248..6a36b2e5b4 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -202,7 +202,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// generator function.
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}},
+ Alloc: types.GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}},
}
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), b.N, gen)
@@ -257,7 +257,7 @@ func BenchmarkChainWrite_full_500k(b *testing.B) {
// makeChainForBench writes a given number of headers or empty blocks/receipts
// into a database.
-func makeChainForBench(db ethdb.Database, full bool, count uint64) {
+func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uint64) {
var hash common.Hash
for n := uint64(0); n < count; n++ {
header := &types.Header{
@@ -269,6 +269,9 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash,
}
+ if n == 0 {
+ header = genesis.ToBlock().Header()
+ }
hash = header.Hash()
rawdb.WriteHeader(db, header)
@@ -276,7 +279,7 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1)))
if n == 0 {
- rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges)
+ rawdb.WriteChainConfig(db, hash, genesis.Config)
}
rawdb.WriteHeadHeaderHash(db, hash)
@@ -291,6 +294,7 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
}
func benchWriteChain(b *testing.B, full bool, count uint64) {
+ genesis := &Genesis{Config: params.AllEthashProtocolChanges}
for i := 0; i < b.N; i++ {
dir := b.TempDir()
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
@@ -299,7 +303,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- makeChainForBench(db, full, count)
+ makeChainForBench(db, genesis, full, count)
db.Close()
}
}
@@ -312,7 +316,8 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- makeChainForBench(db, full, count)
+ genesis := &Genesis{Config: params.AllEthashProtocolChanges}
+ makeChainForBench(db, genesis, full, count)
db.Close()
cacheConfig := *defaultCacheConfig
@@ -327,7 +332,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
+ chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index 8069a3ec5e..d0470b1284 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -110,7 +110,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
gspec = &Genesis{
Config: &config,
ExtraData: make([]byte, 32+common.AddressLength+crypto.SignatureLength),
- Alloc: map[common.Address]GenesisAccount{
+ Alloc: map[common.Address]types.Account{
addr: {Balance: big.NewInt(1)},
},
BaseFee: big.NewInt(params.InitialBaseFee),
diff --git a/core/blockchain.go b/core/blockchain.go
index b1fec32cf3..6d17149798 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -54,9 +54,9 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
"golang.org/x/exp/slices"
)
@@ -159,8 +159,8 @@ type CacheConfig struct {
}
// triedbConfig derives the configures for trie database.
-func (c *CacheConfig) triedbConfig() *trie.Config {
- config := &trie.Config{Preimages: c.Preimages}
+func (c *CacheConfig) triedbConfig() *triedb.Config {
+ config := &triedb.Config{Preimages: c.Preimages}
if c.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
@@ -198,6 +198,13 @@ func DefaultCacheConfigWithScheme(scheme string) *CacheConfig {
var DefaultCacheConfig = defaultCacheConfig
+// txLookup is wrapper over transaction lookup along with the corresponding
+// transaction object.
+type txLookup struct {
+ lookup *rawdb.LegacyTxLookupEntry
+ transaction *types.Transaction
+}
+
// BlockChain represents the canonical chain given a database with a genesis
// block. The Blockchain manages chain imports, reverts, chain reorganisations.
//
@@ -222,15 +229,9 @@ type BlockChain struct {
gcproc time.Duration // Accumulates canonical block processing for trie dumping
lastWrite uint64 // Last block when the state was flushed
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
- triedb *trie.Database // The database handler for maintaining trie nodes.
+ triedb *triedb.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
-
- // txLookupLimit is the maximum number of blocks from head whose tx indices
- // are reserved:
- // * 0: means no limit and regenerate any missing indexes
- // * N: means N block limit [HEAD-N+1, HEAD] and delete extra indexes
- // * nil: disable tx reindexer/deleter, but still index new blocks
- txLookupLimit uint64
+ txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
hc *HeaderChain
rmLogsFeed event.Feed
@@ -255,15 +256,15 @@ type BlockChain struct {
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue]
receiptsCache *lru.Cache[common.Hash, []*types.Receipt]
blockCache *lru.Cache[common.Hash, *types.Block]
- txLookupCache *lru.Cache[common.Hash, *rawdb.LegacyTxLookupEntry]
+ txLookupCache *lru.Cache[common.Hash, txLookup]
// future blocks are blocks added for later processing
futureBlocks *lru.Cache[common.Hash, *types.Block]
- wg sync.WaitGroup //
- quit chan struct{} // shutdown signal, closed in Stop.
- stopping atomic.Bool // false if chain is running, true when stopped
- procInterrupt atomic.Bool // interrupt signaler for block processing
+ wg sync.WaitGroup
+ quit chan struct{} // shutdown signal, closed in Stop.
+ stopping atomic.Bool // false if chain is running, true when stopped
+ procInterrupt atomic.Bool // interrupt signaler for block processing
engine consensus.Engine
validator Validator // Block and state validator interface
@@ -295,7 +296,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
cacheConfig.TriesInMemory = defaultCacheConfig.TriesInMemory
}
// Open trie database with provided config
- triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
+ triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig())
// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
@@ -327,7 +328,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit),
receiptsCache: lru.NewCache[common.Hash, []*types.Receipt](receiptsCacheLimit),
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
- txLookupCache: lru.NewCache[common.Hash, *rawdb.LegacyTxLookupEntry](txLookupCacheLimit),
+ txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks),
engine: engine,
vmConfig: vmConfig,
@@ -513,13 +514,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}
- // Start tx indexer/unindexer if required.
+ // Start tx indexer if it's enabled.
if txLookupLimit != nil {
- bc.txLookupLimit = *txLookupLimit
-
- bc.wg.Add(1)
-
- go bc.maintainTxIndex()
+ bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
}
return bc, nil
@@ -1154,7 +1151,10 @@ func (bc *BlockChain) stopWithoutSaving() {
if !bc.stopping.CompareAndSwap(false, true) {
return
}
-
+ // Signal shutdown tx indexer.
+ if bc.txIndexer != nil {
+ bc.txIndexer.close()
+ }
// Unsubscribe all subscriptions registered from blockchain.
bc.scope.Close()
@@ -1400,12 +1400,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Write all chain data to ancients.
td := bc.GetTd(first.Hash(), first.NumberU64())
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, borReceipts, td)
- size += writeSize
-
if err != nil {
log.Error("Error importing chain data to ancients", "err", err)
return 0, err
}
+ size += writeSize
// Write tx indices if any condition is satisfied:
// * If user requires to reserve all tx indices(txlookuplimit=0)
@@ -1420,7 +1419,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// generated.
batch := bc.db.NewBatch()
for i, block := range blockChain {
- if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit {
+ if bc.txIndexer.limit == 0 || ancientLimit <= bc.txIndexer.limit || block.NumberU64() >= ancientLimit-bc.txIndexer.limit {
rawdb.WriteTxLookupEntriesByBlock(batch, block)
} else if rawdb.ReadTxIndexTail(bc.db) != nil {
rawdb.WriteTxLookupEntriesByBlock(batch, block)
@@ -1461,9 +1460,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
}
// Delete block data from the main database.
- batch.Reset()
-
- canonHashes := make(map[common.Hash]struct{})
+ var (
+ canonHashes = make(map[common.Hash]struct{})
+ )
for _, block := range blockChain {
canonHashes[block.Hash()] = struct{}{}
@@ -1485,15 +1484,18 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return 0, err
}
+ stats.processed += int32(len(blockChain))
return 0, nil
}
// writeLive writes blockchain and corresponding receipt chain into active store.
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
- skipPresenceCheck := false
- batch := bc.db.NewBatch()
headers := make([]*types.Header, 0, len(blockChain))
+ var (
+ skipPresenceCheck = false
+ batch = bc.db.NewBatch()
+ )
for i, block := range blockChain {
// Update the headers for bor specific reorg check
headers = append(headers, block.Header())
@@ -1522,11 +1524,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Write all the data out into the database
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
- rawdb.WriteTxLookupEntriesByBlock(batch, block) // Always write tx indices for live blocks, we assume they are needed
// Write everything belongs to the blocks into the database. So that
- // we can ensure all components of body is completed(body, receipts,
- // tx indexes)
+ // we can ensure all components of body is completed(body, receipts)
+ // except transaction indexes(will be created once sync is finished).
if batch.ValueSize() >= ethdb.IdealBatchSize {
if err := batch.Write(); err != nil {
return 0, err
@@ -1564,19 +1565,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return n, err
}
}
- // Write the tx index tail (block number from where we index) before write any live blocks
- if len(liveBlocks) > 0 && liveBlocks[0].NumberU64() == ancientLimit+1 {
- // The tx index tail can only be one of the following two options:
- // * 0: all ancient blocks have been indexed
- // * ancient-limit: the indices of blocks before ancient-limit are ignored
- if tail := rawdb.ReadTxIndexTail(bc.db); tail == nil {
- if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit {
- rawdb.WriteTxIndexTail(bc.db, 0)
- } else {
- rawdb.WriteTxIndexTail(bc.db, ancientLimit-bc.txLookupLimit)
- }
- }
- }
if len(liveBlocks) > 0 {
if n, err := writeLive(liveBlocks, liveReceipts); err != nil {
@@ -1587,14 +1575,15 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return n, err
}
}
+ var (
+ head = blockChain[len(blockChain)-1]
- head := blockChain[len(blockChain)-1]
-
- context := []interface{}{
- "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
- "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
- "size", common.StorageSize(size),
- }
+ context = []interface{}{
+ "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
+ "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
+ "size", common.StorageSize(size),
+ }
+ )
if stats.ignored > 0 {
context = append(context, []interface{}{"ignored", stats.ignored}...)
}
@@ -1611,7 +1600,6 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
if bc.insertStopped() {
return errInsertionInterrupted
}
-
batch := bc.db.NewBatch()
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
rawdb.WriteBlock(batch, block)
@@ -2973,109 +2961,6 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
return false
}
-// indexBlocks reindexes or unindexes transactions depending on user configuration
-func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
- defer func() { close(done) }()
-
- // If head is 0, it means the chain is just initialized and no blocks are inserted,
- // so don't need to indexing anything.
- if head == 0 {
- return
- }
-
- // The tail flag is not existent, it means the node is just initialized
- // and all blocks(may from ancient store) are not indexed yet.
- if tail == nil {
- from := uint64(0)
- if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
- from = head - bc.txLookupLimit + 1
- }
-
- rawdb.IndexTransactions(bc.db, from, head+1, bc.quit)
-
- return
- }
- // The tail flag is existent, but the whole chain is required to be indexed.
- if bc.txLookupLimit == 0 || head < bc.txLookupLimit {
- if *tail > 0 {
- // It can happen when chain is rewound to a historical point which
- // is even lower than the indexes tail, recap the indexing target
- // to new head to avoid reading non-existent block bodies.
- end := *tail
- if end > head+1 {
- end = head + 1
- }
-
- rawdb.IndexTransactions(bc.db, 0, end, bc.quit)
- }
-
- return
- }
- // Update the transaction index to the new chain state
- if head-bc.txLookupLimit+1 < *tail {
- // Reindex a part of missing indices and rewind index tail to HEAD-limit
- rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit)
- } else {
- // Unindex a part of stale indices and forward index tail to HEAD-limit
- rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit)
- }
-}
-
-// maintainTxIndex is responsible for the construction and deletion of the
-// transaction index.
-//
-// User can use flag `txlookuplimit` to specify a "recentness" block, below
-// which ancient tx indices get deleted. If `txlookuplimit` is 0, it means
-// all tx indices will be reserved.
-//
-// The user can adjust the txlookuplimit value for each launch after sync,
-// Geth will automatically construct the missing indices or delete the extra
-// indices.
-func (bc *BlockChain) maintainTxIndex() {
- defer bc.wg.Done()
-
- // Listening to chain events and manipulate the transaction indexes.
- var (
- done chan struct{} // Non-nil if background unindexing or reindexing routine is active.
- headCh = make(chan ChainHeadEvent, 1) // Buffered to avoid locking up the event feed
- )
-
- sub := bc.SubscribeChainHeadEvent(headCh)
- if sub == nil {
- return
- }
-
- defer sub.Unsubscribe()
- log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
-
- // Launch the initial processing if chain is not empty. This step is
- // useful in these scenarios that chain has no progress and indexer
- // is never triggered.
- if head := rawdb.ReadHeadBlock(bc.db); head != nil {
- done = make(chan struct{})
- go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.NumberU64(), done)
- }
-
- for {
- select {
- case head := <-headCh:
- if done == nil {
- done = make(chan struct{})
- go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), done)
- }
- case <-done:
- done = nil
- case <-bc.quit:
- if done != nil {
- log.Info("Waiting background transaction indexer to exit")
- <-done
- }
-
- return
- }
- }
-}
-
// reportBlock logs a bad block error.
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
rawdb.WriteBadBlock(bc.db, block)
@@ -3151,7 +3036,7 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
bc.flushInterval.Store(int64(interval))
}
-// GetTrieFlushInterval gets the in-memory tries flush interval
+// GetTrieFlushInterval gets the in-memory tries flushAlloc interval
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load())
}
diff --git a/core/blockchain_bor_test.go b/core/blockchain_bor_test.go
index e13dfb35de..cacd1d12e1 100644
--- a/core/blockchain_bor_test.go
+++ b/core/blockchain_bor_test.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func TestChain2HeadEvent(t *testing.T) {
@@ -24,7 +24,7 @@ func TestChain2HeadEvent(t *testing.T) {
Config: params.TestChainConfig,
Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
}
- genesis = gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis = gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
signer = types.LatestSigner(gspec.Config)
)
diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go
index 3630a44e3b..5efbb78595 100644
--- a/core/blockchain_reader.go
+++ b/core/blockchain_reader.go
@@ -17,6 +17,7 @@
package core
import (
+ "errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -30,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// CurrentHeader retrieves the current head header of the canonical chain. The
@@ -287,23 +288,48 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical)
}
-// GetTransactionLookup retrieves the lookup associate with the given transaction
-// hash from the cache or database.
-func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry {
+// GetTransactionLookup retrieves the lookup along with the transaction
+// itself associate with the given transaction hash.
+//
+// An error will be returned if the transaction is not found, and background
+// indexing for transactions is still in progress. The transaction might be
+// reachable shortly once it's indexed.
+//
+// A null will be returned in the transaction is not found and background
+// transaction indexing is already finished. The transaction is not existent
+// from the node's perspective.
+func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
// Short circuit if the txlookup already in the cache, retrieve otherwise
- if lookup, exist := bc.txLookupCache.Get(hash); exist {
- return lookup
+ if item, exist := bc.txLookupCache.Get(hash); exist {
+ return item.lookup, item.transaction, nil
}
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
if tx == nil {
- return nil
+ progress, err := bc.TxIndexProgress()
+ if err != nil {
+ return nil, nil, nil
+ }
+ // The transaction indexing is not finished yet, returning an
+ // error to explicitly indicate it.
+ if !progress.Done() {
+ return nil, nil, errors.New("transaction indexing still in progress")
+ }
+ // The transaction is already indexed, the transaction is either
+ // not existent or not in the range of index, returning null.
+ return nil, nil, nil
}
+ lookup := &rawdb.LegacyTxLookupEntry{
+ BlockHash: blockHash,
+ BlockIndex: blockNumber,
+ Index: txIndex,
+ }
+ bc.txLookupCache.Add(hash, txLookup{
+ lookup: lookup,
+ transaction: tx,
+ })
- lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex}
- bc.txLookupCache.Add(hash, lookup)
-
- return lookup
+ return lookup, tx, nil
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
@@ -407,23 +433,24 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
return &bc.vmConfig
}
-// SetTxLookupLimit is responsible for updating the txlookup limit to the
-// original one stored in db if the new mismatches with the old one.
-func (bc *BlockChain) SetTxLookupLimit(limit uint64) {
- bc.txLookupLimit = limit
-}
-
-// TxLookupLimit retrieves the txlookup limit used by blockchain to prune
-// stale transaction indices.
-func (bc *BlockChain) TxLookupLimit() uint64 {
- return bc.txLookupLimit
+// TxIndexProgress returns the transaction indexing progress.
+func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
+ if bc.txIndexer == nil {
+ return TxIndexProgress{}, errors.New("tx indexer is not enabled")
+ }
+ return bc.txIndexer.txIndexProgress()
}
// TrieDB retrieves the low level trie database used for data storage.
-func (bc *BlockChain) TrieDB() *trie.Database {
+func (bc *BlockChain) TrieDB() *triedb.Database {
return bc.triedb
}
+// HeaderChain returns the underlying header chain.
+func (bc *BlockChain) HeaderChain() *HeaderChain {
+ return bc.hc
+}
+
// SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent.
func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription {
return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch))
diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go
index d1fefd243f..171d08407c 100644
--- a/core/blockchain_sethead_test.go
+++ b/core/blockchain_sethead_test.go
@@ -34,9 +34,9 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// rewindTest is a test case for chain rollback upon user request.
@@ -2035,13 +2035,13 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
}
// Reopen the trie database without persisting in-memory dirty nodes.
chain.triedb.Close()
- dbconfig := &trie.Config{}
+ dbconfig := &triedb.Config{}
if scheme == rawdb.PathScheme {
dbconfig.PathDB = pathdb.Defaults
} else {
dbconfig.HashDB = hashdb.Defaults
}
- chain.triedb = trie.NewDatabase(chain.db, dbconfig)
+ chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
// Force run a freeze cycle
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 519c31fd28..aae759816e 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// So we can deterministically seed different blockchains
@@ -896,7 +897,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
funds = big.NewInt(1000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
signer = types.LatestSigner(gspec.Config)
@@ -1041,7 +1042,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
funds = big.NewInt(1000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
)
@@ -1170,7 +1171,7 @@ func testChainTxReorgs(t *testing.T, scheme string) {
gspec = &Genesis{
Config: params.TestChainConfig,
GasLimit: 3141592,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: big.NewInt(1000000000000000)},
addr2: {Balance: big.NewInt(1000000000000000)},
addr3: {Balance: big.NewInt(1000000000000000)},
@@ -1289,7 +1290,7 @@ func testLogReorgs(t *testing.T, scheme string) {
// this code generates a log
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
+ gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config)
)
@@ -1352,7 +1353,7 @@ func testLogRebirth(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
+ gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker()
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil, nil)
@@ -1442,7 +1443,7 @@ func testSideLogRebirth(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
+ gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config)
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
)
@@ -1553,7 +1554,7 @@ func testReorgSideEvent(t *testing.T, scheme string) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
+ Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
}
signer = types.LatestSigner(gspec.Config)
)
@@ -1706,7 +1707,7 @@ func testEIP155Transition(t *testing.T, scheme string) {
EIP155Block: big.NewInt(2),
HomesteadBlock: new(big.Int),
},
- Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
}
)
@@ -1834,7 +1835,7 @@ func testEIP161AccountRemoval(t *testing.T, scheme string) {
EIP150Block: new(big.Int),
EIP158Block: big.NewInt(2),
},
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}},
}
)
@@ -2083,7 +2084,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
+ gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{address: {Balance: funds}}}
)
height := uint64(1024)
@@ -2311,7 +2312,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
gspec = &Genesis{
Config: &chainConfig,
- Alloc: GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
+ Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
signer = types.LatestSigner(gspec.Config)
@@ -2959,218 +2960,6 @@ func testReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T, scheme strin
}
}
-func TestTransactionIndices(t *testing.T) {
- // Configure and generate a sample block chain
- var (
- key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- address = crypto.PubkeyToAddress(key.PublicKey)
- funds = big.NewInt(100000000000000000)
- gspec = &Genesis{
- Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
- BaseFee: big.NewInt(params.InitialBaseFee),
- }
- signer = types.LatestSigner(gspec.Config)
- )
-
- _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
- if err != nil {
- panic(err)
- }
-
- block.AddTx(tx)
- })
-
- borReceipts := make([]types.Receipts, len(receipts))
-
- check := func(tail *uint64, chain *BlockChain) {
- stored := rawdb.ReadTxIndexTail(chain.db)
- if tail == nil && stored != nil {
- t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored)
- }
-
- if tail != nil && *stored != *tail {
- t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored)
- }
-
- if tail != nil {
- for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
-
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil {
- t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
-
- for i := uint64(0); i < *tail; i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
-
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil {
- t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- }
- }
- // Init block chain with external ancients, check all needed indices has been indexed.
- limit := []uint64{0, 32, 64, 128}
- for _, l := range limit {
- frdir := t.TempDir()
- ancientDb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
- _, _ = rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), append([]types.Receipts{{}}, borReceipts...), big.NewInt(0))
-
- l := l
-
- chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
-
- chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
-
- var tail uint64
- if l != 0 {
- tail = uint64(128) - l + 1
- }
-
- check(&tail, chain)
- chain.Stop()
- ancientDb.Close()
- os.RemoveAll(frdir)
- }
-
- // Reconstruct a block chain which only reserves HEAD-64 tx indices
- ancientDb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false)
- defer ancientDb.Close()
-
- _, _ = rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), append([]types.Receipts{{}}, borReceipts...), big.NewInt(0))
-
- limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */}
-
- for _, l := range limit {
- l := l
-
- chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
-
- var tail uint64
-
- if l != 0 {
- tail = uint64(128) - l + 1
- }
-
- chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
- check(&tail, chain)
- chain.Stop()
- }
-}
-
-func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
- testSkipStaleTxIndicesInSnapSync(t, rawdb.HashScheme)
- testSkipStaleTxIndicesInSnapSync(t, rawdb.PathScheme)
-}
-
-func testSkipStaleTxIndicesInSnapSync(t *testing.T, scheme string) {
- // Configure and generate a sample block chain
- var (
- key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- address = crypto.PubkeyToAddress(key.PublicKey)
- funds = big.NewInt(100000000000000000)
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
- signer = types.LatestSigner(gspec.Config)
- )
-
- _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
- if err != nil {
- panic(err)
- }
-
- block.AddTx(tx)
- })
-
- check := func(tail *uint64, chain *BlockChain) {
- stored := rawdb.ReadTxIndexTail(chain.db)
- if tail == nil && stored != nil {
- t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored)
- }
-
- if tail != nil && *stored != *tail {
- t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored)
- }
-
- if tail != nil {
- for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
-
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil {
- t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
-
- for i := uint64(0); i < *tail; i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
-
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil {
- t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- }
- }
-
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false)
- if err != nil {
- t.Fatalf("failed to create temp freezer db: %v", err)
- }
- defer ancientDb.Close()
-
- // Import all blocks into ancient db, only HEAD-32 indices are kept.
- l := uint64(32)
- chain, err := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
-
- defer chain.Stop()
-
- headers := make([]*types.Header, len(blocks))
- for i, block := range blocks {
- headers[i] = block.Header()
- }
- if n, err := chain.InsertHeaderChain(headers); err != nil {
- t.Fatalf("failed to insert header %d: %v", n, err)
- }
- // The indices before ancient-N(32) should be ignored. After that all blocks should be indexed.
- if n, err := chain.InsertReceiptChain(blocks, receipts, 64); err != nil {
- t.Fatalf("block %d: failed to insert into chain: %v", n, err)
- }
-
- tail := uint64(32)
- check(&tail, chain)
-}
-
// Benchmarks large blocks with value transfers to non-existing accounts
func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) {
var (
@@ -3180,7 +2969,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
bankFunds = big.NewInt(100000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
testBankAddress: {Balance: bankFunds},
common.HexToAddress("0xc0de"): {
Code: []byte{0x60, 0x01, 0x50},
@@ -3376,7 +3165,7 @@ func testDeleteCreateRevert(t *testing.T, scheme string) {
funds = big.NewInt(100000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xAAAAA selfdestructs if called
aa: {
@@ -3502,7 +3291,7 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) {
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xAAAAA selfdestructs if called
aa: {
@@ -3592,7 +3381,7 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) {
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xAAAAA selfdestructs if called
aa: {
@@ -3717,7 +3506,7 @@ func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) {
t.Logf("Destination address: %x\n", aa)
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xAAAAA selfdestructs if called
aa: {
@@ -3932,7 +3721,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address aa has some funds
aa: {Balance: big.NewInt(100000)},
@@ -3966,7 +3755,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
defer chain.Stop()
statedb, _ := chain.State()
- if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
+ if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("Genesis err, got %v exp %v", got, exp)
}
// First block tries to create, but fails
@@ -3977,7 +3766,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
}
statedb, _ = chain.State()
- if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
+ if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp)
}
}
@@ -4010,7 +3799,7 @@ func testEIP2718Transition(t *testing.T, scheme string) {
funds = big.NewInt(1000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xAAAA sloads 0x00 and 0x01
aa: {
@@ -4096,7 +3885,7 @@ func testEIP1559Transition(t *testing.T, scheme string) {
config = *params.AllEthashProtocolChanges
gspec = &Genesis{
Config: &config,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
// The address 0xAAAA sloads 0x00 and 0x01
@@ -4165,10 +3954,10 @@ func testEIP1559Transition(t *testing.T, scheme string) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
@@ -4176,7 +3965,7 @@ func testEIP1559Transition(t *testing.T, scheme string) {
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
@@ -4207,10 +3996,10 @@ func testEIP1559Transition(t *testing.T, scheme string) {
effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()
// 6+5: Ensure that miner received only the tx's effective tip.
- actual = state.GetBalance(block.Coinbase())
+ actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
@@ -4218,7 +4007,7 @@ func testEIP1559Transition(t *testing.T, scheme string) {
}
// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr2))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
@@ -4242,7 +4031,7 @@ func testSetCanonical(t *testing.T, scheme string) {
funds = big.NewInt(100000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
signer = types.LatestSigner(gspec.Config)
@@ -4373,7 +4162,7 @@ func testCanonicalHashMarker(t *testing.T, scheme string) {
var (
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{},
+ Alloc: types.GenesisAlloc{},
BaseFee: big.NewInt(params.InitialBaseFee),
}
engine = ethash.NewFaker()
@@ -4447,225 +4236,6 @@ func testCanonicalHashMarker(t *testing.T, scheme string) {
}
}
-// TestTxIndexer tests the tx indexes are updated correctly.
-func TestTxIndexer(t *testing.T) {
- t.Parallel()
-
- var (
- testBankKey, _ = crypto.GenerateKey()
- testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
- testBankFunds = big.NewInt(1000000000000000000)
-
- gspec = &Genesis{
- Config: params.TestChainConfig,
- Alloc: GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
- BaseFee: big.NewInt(params.InitialBaseFee),
- }
- engine = ethash.NewFaker()
- nonce = uint64(0)
- )
-
- _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, 128, func(i int, gen *BlockGen) {
- tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey)
- gen.AddTx(tx)
-
- nonce += 1
- })
-
- // verifyIndexes checks if the transaction indexes are present or not
- // of the specified block.
- verifyIndexes := func(db ethdb.Database, number uint64, exist bool) {
- if number == 0 {
- return
- }
-
- block := blocks[number-1]
-
- for _, tx := range block.Transactions() {
- lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
- if exist && lookup == nil {
- t.Fatalf("missing %d %x", number, tx.Hash().Hex())
- }
-
- if !exist && lookup != nil {
- t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
- }
- }
- }
- // verifyRange runs verifyIndexes for a range of blocks, from and to are included.
- verifyRange := func(db ethdb.Database, from, to uint64, exist bool) {
- for number := from; number <= to; number += 1 {
- verifyIndexes(db, number, exist)
- }
- }
- verify := func(db ethdb.Database, expTail uint64) {
- tail := rawdb.ReadTxIndexTail(db)
- if tail == nil {
- t.Fatal("Failed to write tx index tail")
- }
-
- if *tail != expTail {
- t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
- }
-
- if *tail != 0 {
- verifyRange(db, 0, *tail-1, false)
- }
-
- verifyRange(db, *tail, 128, true)
- }
-
- var cases = []struct {
- limitA uint64
- tailA uint64
- limitB uint64
- tailB uint64
- limitC uint64
- tailC uint64
- }{
- {
- // LimitA: 0
- // TailA: 0
- //
- // all blocks are indexed
- limitA: 0,
- tailA: 0,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 64
- // TailA: 65
- //
- // block [65, 128] are indexed
- limitA: 64,
- tailA: 65,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 127
- // TailA: 2
- //
- // block [2, 128] are indexed
- limitA: 127,
- tailA: 2,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 128
- // TailA: 1
- //
- // block [2, 128] are indexed
- limitA: 128,
- tailA: 1,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 129
- // TailA: 0
- //
- // block [0, 128] are indexed
- limitA: 129,
- tailA: 0,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- }
-
- borReceipts := make([]types.Receipts, len(receipts))
-
- for _, c := range cases {
- frdir := t.TempDir()
- db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
- _, _ = rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), append([]types.Receipts{{}}, borReceipts...), big.NewInt(0))
-
- // Index the initial blocks from ancient store
- chain, _ := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, &c.limitA, nil)
- chain.indexBlocks(nil, 128, make(chan struct{}))
- verify(db, c.tailA)
-
- chain.SetTxLookupLimit(c.limitB)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, c.tailB)
-
- chain.SetTxLookupLimit(c.limitC)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, c.tailC)
-
- // Recover all indexes
- chain.SetTxLookupLimit(0)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, 0)
-
- chain.Stop()
- db.Close()
- os.RemoveAll(frdir)
- }
-}
-
func TestCreateThenDeletePreByzantium(t *testing.T) {
t.Parallel()
@@ -4719,7 +4289,7 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
}...)
gspec := &Genesis{
Config: config,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
},
}
@@ -4809,7 +4379,7 @@ func TestDeleteThenCreate(t *testing.T) {
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
},
}
@@ -4924,7 +4494,7 @@ func TestTransientStorageReset(t *testing.T) {
}...)
gspec := &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
},
}
@@ -5000,7 +4570,7 @@ func TestEIP3651(t *testing.T) {
config = *params.AllEthashProtocolChanges
gspec = &Genesis{
Config: &config,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
// The address 0xAAAA sloads 0x00 and 0x01
@@ -5085,7 +4655,7 @@ func TestEIP3651(t *testing.T) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
if actual.Cmp(expected) != 0 {
@@ -5093,7 +4663,7 @@ func TestEIP3651(t *testing.T) {
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
diff --git a/core/chain_makers.go b/core/chain_makers.go
index d55fcd14cc..9180304b22 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -32,7 +32,8 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
)
// BlockGen creates blocks for testing.
@@ -85,7 +86,7 @@ func (b *BlockGen) SetDifficulty(diff *big.Int) {
b.header.Difficulty = diff
}
-// SetPos makes the header a PoS-header (0 difficulty)
+// SetPoS makes the header a PoS-header (0 difficulty)
func (b *BlockGen) SetPoS() {
b.header.Difficulty = new(big.Int)
}
@@ -162,7 +163,7 @@ func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) {
}
// GetBalance returns the balance of the given address at the generated block.
-func (b *BlockGen) GetBalance(addr common.Address) *big.Int {
+func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int {
return b.statedb.GetBalance(addr)
}
@@ -324,7 +325,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
cm := newChainMaker(parent, config, engine)
- genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
+ genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
b.header = cm.makeHeader(parent, statedb, b.engine)
@@ -375,7 +376,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
// Forcibly use hash-based state scheme for retaining all nodes in disk.
- triedb := trie.NewDatabase(db, trie.HashDefaults)
+ triedb := triedb.NewDatabase(db, triedb.HashDefaults)
defer triedb.Close()
for i := 0; i < n; i++ {
@@ -420,7 +421,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
// then generate chain on top.
func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
db := rawdb.NewMemoryDatabase()
- triedb := trie.NewDatabase(db, trie.HashDefaults)
+ triedb := triedb.NewDatabase(db, triedb.HashDefaults)
defer triedb.Close()
_, err := genesis.Commit(db, triedb)
if err != nil {
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 7261d87239..e7a4874b25 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func TestGeneratePOSChain(t *testing.T) {
@@ -46,7 +46,7 @@ func TestGeneratePOSChain(t *testing.T) {
asm4788 = common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500")
gspec = &Genesis{
Config: &config,
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: asm4788},
},
@@ -71,19 +71,19 @@ func TestGeneratePOSChain(t *testing.T) {
storage[common.Hash{0x01}] = common.Hash{0x01}
storage[common.Hash{0x02}] = common.Hash{0x02}
storage[common.Hash{0x03}] = common.HexToHash("0303")
- gspec.Alloc[aa] = GenesisAccount{
+ gspec.Alloc[aa] = types.Account{
Balance: common.Big1,
Nonce: 1,
Storage: storage,
Code: common.Hex2Bytes("6042"),
}
- gspec.Alloc[bb] = GenesisAccount{
+ gspec.Alloc[bb] = types.Account{
Balance: common.Big2,
Nonce: 1,
Storage: storage,
Code: common.Hex2Bytes("600154600354"),
}
- genesis := gspec.MustCommit(gendb, trie.NewDatabase(gendb, trie.HashDefaults))
+ genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, triedb.HashDefaults))
genchain, genreceipts := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
gen.SetParentBeaconRoot(common.Hash{byte(i + 1)})
@@ -208,9 +208,9 @@ func ExampleGenerateChain() {
// Ensure that key1 has some funds in the genesis block.
gspec := &Genesis{
Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)},
- Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
+ Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
}
- genesis := gspec.MustCommit(genDb, trie.NewDatabase(genDb, trie.HashDefaults))
+ genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, triedb.HashDefaults))
// This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the
diff --git a/core/error.go b/core/error.go
index 4214ed207a..72cacf8c78 100644
--- a/core/error.go
+++ b/core/error.go
@@ -104,4 +104,10 @@ var (
// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
// blob gas fee of the block.
ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee")
+
+ // ErrMissingBlobHashes is returned if a blob transaction has no blob hashes.
+ ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes")
+
+ // ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
+ ErrBlobTxCreate = errors.New("blob transaction of type create")
)
diff --git a/core/evm.go b/core/evm.go
index 3b280964b7..5500835186 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/holiman/uint256"
)
// ChainContext supports retrieving headers and consensus parameters from the
@@ -142,12 +143,12 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
-func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
+func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0
}
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
-func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
+func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
// get inputs before
input1 := db.GetBalance(sender)
input2 := db.GetBalance(recipient)
@@ -160,5 +161,5 @@ func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int)
output2 := db.GetBalance(recipient)
// add transfer log
- AddTransferLog(db, sender, recipient, amount, input1, input2, output1, output2)
+ AddTransferLog(db, sender, recipient, amount.ToBig(), input1.ToBig(), input2.ToBig(), output1.ToBig(), output2.ToBig())
}
diff --git a/core/forkchoice_test.go b/core/forkchoice_test.go
index 9d111adb44..3e3de28b3e 100644
--- a/core/forkchoice_test.go
+++ b/core/forkchoice_test.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/stretchr/testify/require"
)
@@ -94,7 +94,7 @@ func TestPastChainInsert(t *testing.T) {
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
)
- _, _ = gspec.Commit(db, trie.NewDatabase(db, trie.HashDefaults))
+ _, _ = gspec.Commit(db, triedb.NewDatabase(db, triedb.HashDefaults))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil {
@@ -166,7 +166,7 @@ func TestFutureChainInsert(t *testing.T) {
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
)
- _, _ = gspec.Commit(db, trie.NewDatabase(db, trie.HashDefaults))
+ _, _ = gspec.Commit(db, triedb.NewDatabase(db, triedb.HashDefaults))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil {
@@ -226,7 +226,7 @@ func TestOverlappingChainInsert(t *testing.T) {
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
)
- _, _ = gspec.Commit(db, trie.NewDatabase(db, trie.HashDefaults))
+ _, _ = gspec.Commit(db, triedb.NewDatabase(db, triedb.HashDefaults))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil {
diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go
index 600e5fce79..73ca538cb5 100644
--- a/core/forkid/forkid_test.go
+++ b/core/forkid/forkid_test.go
@@ -49,30 +49,36 @@ func TestCreation(t *testing.T) {
params.MainnetChainConfig,
core.DefaultGenesisBlock().ToBlock(),
[]testcase{
- {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced
- {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block
- {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // First Homestead block
- {1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // Last Homestead block
- {1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // First DAO block
- {2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // Last DAO block
- {2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // First Tangerine block
- {2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // Last Tangerine block
- {2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // First Spurious block
- {4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // Last Spurious block
- {4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // First Byzantium block
- {7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // Last Byzantium block
- {7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // First and last Constantinople, first Petersburg block
- {9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // Last Petersburg block
- {9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // First Istanbul and first Muir Glacier block
- {9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // Last Istanbul and first Muir Glacier block
- {9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // First Muir Glacier block
- {12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block
- {12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block
- {12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block
- {12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // First London block
- {13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // Last London block
- {13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // First Arrow Glacier block
- {15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // Last Arrow Glacier block
+ {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced
+ {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block
+ {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // First Homestead block
+ {1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // Last Homestead block
+ {1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // First DAO block
+ {2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // Last DAO block
+ {2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // First Tangerine block
+ {2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // Last Tangerine block
+ {2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // First Spurious block
+ {4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // Last Spurious block
+ {4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // First Byzantium block
+ {7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // Last Byzantium block
+ {7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // First and last Constantinople, first Petersburg block
+ {9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // Last Petersburg block
+ {9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // First Istanbul and first Muir Glacier block
+ {9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // Last Istanbul and first Muir Glacier block
+ {9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // First Muir Glacier block
+ {12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block
+ {12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block
+ {12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block
+ {12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // First London block
+ {13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // Last London block
+ {13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // First Arrow Glacier block
+ {15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // Last Arrow Glacier block
+ {15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // First Gray Glacier block
+ {20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block
+ {20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // First Shanghai block
+ {30000000, 1710338134, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // Last Shanghai block
+ {40000000, 1710338135, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // First Cancun block
+ {50000000, 2000000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // Future Cancun block
},
},
// Goerli test cases
@@ -80,12 +86,18 @@ func TestCreation(t *testing.T) {
params.GoerliChainConfig,
core.DefaultGoerliGenesisBlock().ToBlock(),
[]testcase{
- {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
- {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block
- {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block
- {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block
- {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block
- {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block
+ {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
+ {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block
+ {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block
+ {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block
+ {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block
+ {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block
+ {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block
+ {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block
+ {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // First Shanghai block
+ {6500002, 1705473119, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // Last Shanghai block
+ {6500003, 1705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // First Cancun block
+ {6500003, 2705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // Future Cancun block
},
},
// Sepolia test cases
@@ -93,8 +105,27 @@ func TestCreation(t *testing.T) {
params.SepoliaChainConfig,
core.DefaultSepoliaGenesisBlock().ToBlock(),
[]testcase{
- {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block
- {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block
+ {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block
+ {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block
+ {1735371, 0, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block
+ {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
+ },
+ },
+ // Holesky test cases
+ {
+ params.HoleskyChainConfig,
+ core.DefaultHoleskyGenesisBlock().ToBlock(),
+ []testcase{
+ {0, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris block
+ {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
},
},
}
@@ -188,14 +219,10 @@ func TestValidation(t *testing.T) {
// at some future block 88888888, for itself, but past block for local. Local is incompatible.
//
// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
- //
- // TODO(karalabe): This testcase will fail once mainnet gets timestamped forks, make legacy chain config
{&legacyConfig, 88888888, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 88888888}, ErrLocalIncompatibleOrStale},
// Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing
// fork) at block 7279999, before Petersburg. Local is incompatible.
- //
- // TODO(karalabe): This testcase will fail once mainnet gets timestamped forks, make legacy chain config
{&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7279999}, ErrLocalIncompatibleOrStale},
//------------------------------------
@@ -250,34 +277,25 @@ func TestValidation(t *testing.T) {
// Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces
// also Shanghai, but it's not yet aware of Cancun (e.g. non updated node before the fork).
// In this case we don't know if Cancun passed yet or not.
- //
- // TODO(karalabe): Enable this when Cancun is specced
- //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, nil},
+ {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, nil},
// Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces
// also Shanghai, and it's also aware of Cancun (e.g. updated node before the fork). We
// don't know if Cancun passed yet (will pass) or not.
- //
- // TODO(karalabe): Enable this when Cancun is specced and update next timestamp
- //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil},
+ {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil},
// Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces
// also Shanghai, and it's also aware of some random fork (e.g. misconfigured Cancun). As
// neither forks passed at neither nodes, they may mismatch, but we still connect for now.
- //
- // TODO(karalabe): Enable this when Cancun is specced
- //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: math.MaxUint64}, nil},
+ {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: math.MaxUint64}, nil},
// Local is mainnet exactly on Cancun, remote announces Shanghai + knowledge about Cancun. Remote
// is simply out of sync, accept.
- //
- // TODO(karalabe): Enable this when Cancun is specced, update local head and time, next timestamp
- // {params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil},
+ {params.MainnetChainConfig, 21000000, 1710338135, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil},
// Local is mainnet Cancun, remote announces Shanghai + knowledge about Cancun. Remote
// is simply out of sync, accept.
- // TODO(karalabe): Enable this when Cancun is specced, update local head and time, next timestamp
- //{params.MainnetChainConfig, 21123456, 1678123456, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil},
+ {params.MainnetChainConfig, 21123456, 1710338136, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil},
// Local is mainnet Prague, remote announces Shanghai + knowledge about Cancun. Remote
// is definitely out of sync. It may or may not need the Prague update, we don't know yet.
@@ -286,9 +304,7 @@ func TestValidation(t *testing.T) {
//{params.MainnetChainConfig, 0, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil},
// Local is mainnet Shanghai, remote announces Cancun. Local is out of sync, accept.
- //
- // TODO(karalabe): Enable this when Cancun is specced, update remote checksum
- //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil},
+ {params.MainnetChainConfig, 21000000, 1700000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}, nil},
// Local is mainnet Shanghai, remote announces Cancun, but is not aware of Prague. Local
// out of sync. Local also knows about a future fork, but that is uncertain yet.
@@ -298,9 +314,7 @@ func TestValidation(t *testing.T) {
// Local is mainnet Cancun. remote announces Shanghai but is not aware of further forks.
// Remote needs software update.
- //
- // TODO(karalabe): Enable this when Cancun is specced, update local head and time
- //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, ErrRemoteStale},
+ {params.MainnetChainConfig, 21000000, 1710338135, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, ErrRemoteStale},
// Local is mainnet Shanghai, and isn't aware of more forks. Remote announces Shanghai +
// 0xffffffff. Local needs software update, reject.
@@ -308,24 +322,20 @@ func TestValidation(t *testing.T) {
// Local is mainnet Shanghai, and is aware of Cancun. Remote announces Cancun +
// 0xffffffff. Local needs software update, reject.
- //
- // TODO(karalabe): Enable this when Cancun is specced, update remote checksum
- //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(checksumUpdate(0x00000000, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale},
+ {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(checksumUpdate(0x9f3d2254, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale},
// Local is mainnet Shanghai, remote is random Shanghai.
{params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x12345678), Next: 0}, ErrLocalIncompatibleOrStale},
- // Local is mainnet Shanghai, far in the future. Remote announces Gopherium (non existing fork)
+ // Local is mainnet Cancun, far in the future. Remote announces Gopherium (non existing fork)
// at some future timestamp 8888888888, for itself, but past block for local. Local is incompatible.
//
// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
- {params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0xdce96c2d), Next: 8888888888}, ErrLocalIncompatibleOrStale},
+ {params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0x9f3d2254), Next: 8888888888}, ErrLocalIncompatibleOrStale},
// Local is mainnet Shanghai. Remote is also in Shanghai, but announces Gopherium (non existing
// fork) at timestamp 1668000000, before Cancun. Local is incompatible.
- //
- // TODO(karalabe): Enable this when Cancun is specced
- //{params.MainnetChainConfig, 20999999, 1677999999, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, ErrLocalIncompatibleOrStale},
+ {params.MainnetChainConfig, 20999999, 1699999999, ID{Hash: checksumToBytes(0x71147644), Next: 1700000000}, ErrLocalIncompatibleOrStale},
}
genesis := core.DefaultGenesisBlock().ToBlock()
for i, tt := range tests {
diff --git a/core/gen_genesis.go b/core/gen_genesis.go
index 553471bd28..8aeb70acc9 100644
--- a/core/gen_genesis.go
+++ b/core/gen_genesis.go
@@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
@@ -18,21 +19,21 @@ var _ = (*genesisSpecMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (g Genesis) MarshalJSON() ([]byte, error) {
type Genesis struct {
- Config *params.ChainConfig `json:"config"`
- Nonce math.HexOrDecimal64 `json:"nonce"`
- Timestamp math.HexOrDecimal64 `json:"timestamp"`
- ExtraData hexutil.Bytes `json:"extraData"`
- GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
- Mixhash common.Hash `json:"mixHash"`
- Coinbase common.Address `json:"coinbase"`
- Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
- Number math.HexOrDecimal64 `json:"number"`
- GasUsed math.HexOrDecimal64 `json:"gasUsed"`
- ParentHash common.Hash `json:"parentHash"`
- BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
- BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
+ Config *params.ChainConfig `json:"config"`
+ Nonce math.HexOrDecimal64 `json:"nonce"`
+ Timestamp math.HexOrDecimal64 `json:"timestamp"`
+ ExtraData hexutil.Bytes `json:"extraData"`
+ GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
+ Mixhash common.Hash `json:"mixHash"`
+ Coinbase common.Address `json:"coinbase"`
+ Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
+ Number math.HexOrDecimal64 `json:"number"`
+ GasUsed math.HexOrDecimal64 `json:"gasUsed"`
+ ParentHash common.Hash `json:"parentHash"`
+ BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
}
var enc Genesis
@@ -46,7 +47,7 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
enc.Coinbase = g.Coinbase
if g.Alloc != nil {
- enc.Alloc = make(map[common.UnprefixedAddress]GenesisAccount, len(g.Alloc))
+ enc.Alloc = make(map[common.UnprefixedAddress]types.Account, len(g.Alloc))
for k, v := range g.Alloc {
enc.Alloc[common.UnprefixedAddress(k)] = v
}
@@ -64,21 +65,21 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (g *Genesis) UnmarshalJSON(input []byte) error {
type Genesis struct {
- Config *params.ChainConfig `json:"config"`
- Nonce *math.HexOrDecimal64 `json:"nonce"`
- Timestamp *math.HexOrDecimal64 `json:"timestamp"`
- ExtraData *hexutil.Bytes `json:"extraData"`
- GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
- Mixhash *common.Hash `json:"mixHash"`
- Coinbase *common.Address `json:"coinbase"`
- Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
- Number *math.HexOrDecimal64 `json:"number"`
- GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
- ParentHash *common.Hash `json:"parentHash"`
- BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
- BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
+ Config *params.ChainConfig `json:"config"`
+ Nonce *math.HexOrDecimal64 `json:"nonce"`
+ Timestamp *math.HexOrDecimal64 `json:"timestamp"`
+ ExtraData *hexutil.Bytes `json:"extraData"`
+ GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
+ Mixhash *common.Hash `json:"mixHash"`
+ Coinbase *common.Address `json:"coinbase"`
+ Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
+ Number *math.HexOrDecimal64 `json:"number"`
+ GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
+ ParentHash *common.Hash `json:"parentHash"`
+ BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
}
var dec Genesis
@@ -125,7 +126,7 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'alloc' for Genesis")
}
- g.Alloc = make(GenesisAlloc, len(dec.Alloc))
+ g.Alloc = make(types.GenesisAlloc, len(dec.Alloc))
for k, v := range dec.Alloc {
g.Alloc[common.Address(k)] = v
}
diff --git a/core/genesis.go b/core/genesis.go
index f0de5093c6..3751c0cd7f 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -19,7 +19,6 @@ package core
import (
"bytes"
"embed"
- "encoding/hex"
"encoding/json"
"errors"
"fmt"
@@ -38,17 +37,24 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
)
//go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
-//go:generate go run github.com/fjl/gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go
//go:embed allocs
var allocs embed.FS
var errGenesisNoConfig = errors.New("genesis has no chain configuration")
+// Deprecated: use types.GenesisAccount instead.
+type GenesisAccount = types.Account
+
+// Deprecated: use types.GenesisAlloc instead.
+type GenesisAlloc = types.GenesisAlloc
+
// Genesis specifies the header fields, state of a genesis block. It also defines hard
// fork switch-over blocks through the chain configuration.
type Genesis struct {
@@ -60,7 +66,7 @@ type Genesis struct {
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
- Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
+ Alloc types.GenesisAlloc `json:"alloc" gencodec:"required"`
// These fields are used for consensus tests. Please don't use them
// in actual genesis blocks.
@@ -120,31 +126,14 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
return &genesis, nil
}
-// GenesisAlloc specifies the initial state that is part of the genesis block.
-type GenesisAlloc map[common.Address]GenesisAccount
-
-func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
- m := make(map[common.UnprefixedAddress]GenesisAccount)
- if err := json.Unmarshal(data, &m); err != nil {
- return err
- }
-
- *ga = make(GenesisAlloc)
- for addr, a := range m {
- (*ga)[common.Address(addr)] = a
- }
-
- return nil
-}
-
-// hash computes the state root according to the genesis specification.
-func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
+// hashAlloc computes the state root according to the genesis specification.
+func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// If a genesis-time verkle trie is requested, create a trie config
// with the verkle trie enabled so that the tree can be initialized
// as such.
- var config *trie.Config
+ var config *triedb.Config
if isVerkle {
- config = &trie.Config{
+ config = &triedb.Config{
PathDB: pathdb.Defaults,
IsVerkle: true,
}
@@ -159,7 +148,7 @@ func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
for addr, account := range *ga {
if account.Balance != nil {
- statedb.AddBalance(addr, account.Balance)
+ statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
@@ -171,10 +160,10 @@ func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
return statedb.Commit(0, false)
}
-// flush is very similar with hash, but the main difference is all the generated
+// flushAlloc is very similar with hash, but the main difference is all the generated
// states will be persisted into the given database. Also, the genesis state
// specification will be flushed as well.
-func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
+func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Database, blockhash common.Hash) error {
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
if err != nil {
return err
@@ -182,7 +171,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
for addr, account := range *ga {
if account.Balance != nil {
- statedb.AddBalance(addr, account.Balance)
+ statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
@@ -212,15 +201,6 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
return nil
}
-// GenesisAccount is an account in the state of the genesis block.
-type GenesisAccount struct {
- Code []byte `json:"code,omitempty"`
- Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
- Balance *big.Int `json:"balance" gencodec:"required"`
- Nonce uint64 `json:"nonce,omitempty"`
- PrivateKey []byte `json:"secretKey,omitempty"` // for tests
-}
-
// field type overrides for gencodec
type genesisSpecMarshaling struct {
Nonce math.HexOrDecimal64
@@ -230,42 +210,12 @@ type genesisSpecMarshaling struct {
GasUsed math.HexOrDecimal64
Number math.HexOrDecimal64
Difficulty *math.HexOrDecimal256
- Alloc map[common.UnprefixedAddress]GenesisAccount
+ Alloc map[common.UnprefixedAddress]types.Account
BaseFee *math.HexOrDecimal256
ExcessBlobGas *math.HexOrDecimal64
BlobGasUsed *math.HexOrDecimal64
}
-type genesisAccountMarshaling struct {
- Code hexutil.Bytes
- Balance *math.HexOrDecimal256
- Nonce math.HexOrDecimal64
- Storage map[storageJSON]storageJSON
- PrivateKey hexutil.Bytes
-}
-
-// storageJSON represents a 256 bit byte array, but allows less than 256 bits when
-// unmarshaling from hex.
-type storageJSON common.Hash
-
-func (h *storageJSON) UnmarshalText(text []byte) error {
- text = bytes.TrimPrefix(text, []byte("0x"))
- if len(text) > 64 {
- return fmt.Errorf("too many hex characters in storage key/value %q", text)
- }
-
- offset := len(h) - len(text)/2 // pad on the left
- if _, err := hex.Decode(h[offset:], text); err != nil {
- return fmt.Errorf("invalid hex storage key/value %q", text)
- }
-
- return nil
-}
-
-func (h storageJSON) MarshalText() ([]byte, error) {
- return hexutil.Bytes(h[:]).MarshalText()
-}
-
// GenesisMismatchError is raised when trying to overwrite an existing
// genesis block with an incompatible one.
type GenesisMismatchError struct {
@@ -295,12 +245,11 @@ type ChainOverrides struct {
// error is a *params.ConfigCompatError and the new, unwritten config is returned.
//
// The returned chain configuration is never nil.
-func SetupGenesisBlock(db ethdb.Database, triedb *trie.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
+func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlockWithOverride(db, triedb, genesis, nil)
}
-// nolint:gocognit
-func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) {
+func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) {
if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
}
@@ -449,6 +398,8 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
return g.Config
case ghash == params.MainnetGenesisHash:
return params.MainnetChainConfig
+ case ghash == params.HoleskyGenesisHash:
+ return params.HoleskyChainConfig
case ghash == params.SepoliaGenesisHash:
return params.SepoliaChainConfig
case ghash == params.GoerliGenesisHash:
@@ -472,7 +423,7 @@ func (g *Genesis) IsVerkle() bool {
// ToBlock returns the genesis block according to genesis specification.
func (g *Genesis) ToBlock() *types.Block {
- root, err := g.Alloc.hash(g.IsVerkle())
+ root, err := hashAlloc(&g.Alloc, g.IsVerkle())
if err != nil {
panic(err)
}
@@ -526,7 +477,7 @@ func (g *Genesis) ToBlock() *types.Block {
// Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block.
-func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block, error) {
+func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) {
block := g.ToBlock()
if block.Number().Sign() != 0 {
return nil, errors.New("can't commit genesis block with number > 0")
@@ -541,10 +492,10 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
return nil, errors.New("can't start clique chain without signers")
}
- // All the checks has passed, flush the states derived from the genesis
+ // All the checks has passed, flushAlloc the states derived from the genesis
// specification as well as the specification itself into the provided
// database.
- if err := g.Alloc.flush(db, triedb, block.Hash()); err != nil {
+ if err := flushAlloc(&g.Alloc, db, triedb, block.Hash()); err != nil {
return nil, err
}
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
@@ -560,7 +511,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block
// MustCommit writes the genesis block and state to db, panicking on error.
// The block is committed as the canonical head block.
-func (g *Genesis) MustCommit(db ethdb.Database, triedb *trie.Database) *types.Block {
+func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.Block {
block, err := g.Commit(db, triedb)
if err != nil {
panic(err)
@@ -575,7 +526,7 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big
Alloc: GenesisAlloc{addr: {Balance: balance}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
- return g.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ return g.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
}
// DefaultGenesisBlock returns the Ethereum main net genesis block.
@@ -615,6 +566,18 @@ func DefaultSepoliaGenesisBlock() *Genesis {
}
}
+// DefaultHoleskyGenesisBlock returns the Holesky network genesis block.
+func DefaultHoleskyGenesisBlock() *Genesis {
+ return &Genesis{
+ Config: params.HoleskyChainConfig,
+ Nonce: 0x1234,
+ GasLimit: 0x17d7840,
+ Difficulty: big.NewInt(0x01),
+ Timestamp: 1695902100,
+ Alloc: decodePrealloc(holeskyAllocData),
+ }
+}
+
// DefaultMumbaiGenesisBlock returns the Mumbai network genesis block.
func DefaultMumbaiGenesisBlock() *Genesis {
return &Genesis{
@@ -668,7 +631,7 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
GasLimit: gasLimit,
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: big.NewInt(1),
- Alloc: map[common.Address]GenesisAccount{
+ Alloc: map[common.Address]types.Account{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
@@ -681,12 +644,12 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
},
}
if faucet != nil {
- genesis.Alloc[*faucet] = GenesisAccount{Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}
+ genesis.Alloc[*faucet] = types.Account{Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}
}
return genesis
}
-func decodePrealloc(data string) GenesisAlloc {
+func decodePrealloc(data string) types.GenesisAlloc {
var p []struct {
Addr *big.Int
Balance *big.Int
@@ -703,9 +666,9 @@ func decodePrealloc(data string) GenesisAlloc {
panic(err)
}
- ga := make(GenesisAlloc, len(p))
+ ga := make(types.GenesisAlloc, len(p))
for _, account := range p {
- acc := GenesisAccount{Balance: account.Balance}
+ acc := types.Account{Balance: account.Balance}
if account.Misc != nil {
acc.Nonce = account.Misc.Nonce
acc.Code = account.Misc.Code
diff --git a/core/genesis_test.go b/core/genesis_test.go
index 25a406bf6b..0257ecfa0c 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -27,18 +27,19 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
func TestInvalidCliqueConfig(t *testing.T) {
block := DefaultGoerliGenesisBlock()
block.ExtraData = []byte{}
db := rawdb.NewMemoryDatabase()
- if _, err := block.Commit(db, trie.NewDatabase(db, nil)); err == nil {
+ if _, err := block.Commit(db, triedb.NewDatabase(db, nil)); err == nil {
t.Fatal("Expected error on invalid clique config")
}
}
@@ -53,7 +54,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
customg = Genesis{
Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)},
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
},
}
@@ -72,7 +73,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "genesis without ChainConfig",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
+ return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
},
wantErr: errGenesisNoConfig,
wantConfig: params.AllEthashProtocolChanges,
@@ -80,7 +81,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "no block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
+ return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
},
wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig,
@@ -88,8 +89,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "mainnet block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- DefaultGenesisBlock().MustCommit(db, trie.NewDatabase(db, newDbConfig(scheme)))
- return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
+ DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme)))
+ return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
},
wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig,
@@ -97,7 +98,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "custom block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- tdb := trie.NewDatabase(db, newDbConfig(scheme))
+ tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, nil)
},
@@ -107,7 +108,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "custom block in DB, genesis == goerli",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- tdb := trie.NewDatabase(db, newDbConfig(scheme))
+ tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock())
},
@@ -118,7 +119,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
{
name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
- tdb := trie.NewDatabase(db, newDbConfig(scheme))
+ tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, &customg)
},
@@ -130,7 +131,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
// Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg.
- tdb := trie.NewDatabase(db, newDbConfig(scheme))
+ tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb)
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil, nil)
@@ -191,7 +192,7 @@ func TestGenesisHashes(t *testing.T) {
} {
// Test via MustCommit
db := rawdb.NewMemoryDatabase()
- if have := c.genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)).Hash(); have != c.want {
+ if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want {
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
}
// Test via ToBlock
@@ -209,7 +210,7 @@ func TestGenesis_Commit(t *testing.T) {
}
db := rawdb.NewMemoryDatabase()
- genesisBlock := genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
if genesis.Difficulty != nil {
t.Fatalf("assumption wrong")
@@ -231,19 +232,18 @@ func TestGenesis_Commit(t *testing.T) {
func TestReadWriteGenesisAlloc(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
- alloc = &GenesisAlloc{
+ alloc = &types.GenesisAlloc{
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
}
- hash, _ = alloc.hash(false)
+ hash, _ = hashAlloc(alloc, false)
)
// nolint : errchkjson
blob, _ := json.Marshal(alloc)
rawdb.WriteGenesisStateSpec(db, hash, blob)
- var reload GenesisAlloc
-
+ var reload types.GenesisAlloc
err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash))
if err != nil {
t.Fatalf("Failed to load genesis state %v", err)
@@ -265,11 +265,11 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
}
}
-func newDbConfig(scheme string) *trie.Config {
+func newDbConfig(scheme string) *triedb.Config {
if scheme == rawdb.HashScheme {
- return trie.HashDefaults
+ return triedb.HashDefaults
}
- return &trie.Config{PathDB: pathdb.Defaults}
+ return &triedb.Config{PathDB: pathdb.Defaults}
}
func TestVerkleGenesisCommit(t *testing.T) {
@@ -308,7 +308,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
Config: verkleConfig,
Timestamp: verkleTime,
Difficulty: big.NewInt(0),
- Alloc: GenesisAlloc{
+ Alloc: types.GenesisAlloc{
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
},
}
@@ -320,7 +320,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
}
db := rawdb.NewMemoryDatabase()
- triedb := trie.NewDatabase(db, &trie.Config{IsVerkle: true, PathDB: pathdb.Defaults})
+ triedb := triedb.NewDatabase(db, &triedb.Config{IsVerkle: true, PathDB: pathdb.Defaults})
block := genesis.MustCommit(db, triedb)
if !bytes.Equal(block.Root().Bytes(), expected) {
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
diff --git a/core/headerchain_test.go b/core/headerchain_test.go
index c7f72f48b3..80e3305278 100644
--- a/core/headerchain_test.go
+++ b/core/headerchain_test.go
@@ -28,7 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func verifyUnbrokenCanonchain(hc *HeaderChain) error {
@@ -78,7 +78,7 @@ func TestHeaderInsertion(t *testing.T) {
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
)
- gspec.Commit(db, trie.NewDatabase(db, nil))
+ gspec.Commit(db, triedb.NewDatabase(db, nil))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil {
t.Fatal(err)
diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go
index 2074c9727b..df82347462 100644
--- a/core/parallel_state_processor.go
+++ b/core/parallel_state_processor.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/blockstm"
@@ -186,10 +187,10 @@ func (task *ExecutionTask) Settle() {
if *task.shouldDelayFeeCal {
if task.config.IsLondon(task.blockNumber) {
- task.finalStateDB.AddBalance(task.result.BurntContractAddress, task.result.FeeBurnt)
+ task.finalStateDB.AddBalance(task.result.BurntContractAddress, cmath.BigIntToUint256Int(task.result.FeeBurnt))
}
- task.finalStateDB.AddBalance(task.coinbase, task.result.FeeTipped)
+ task.finalStateDB.AddBalance(task.coinbase, cmath.BigIntToUint256Int(task.result.FeeTipped))
output1 := new(big.Int).SetBytes(task.result.SenderInitBalance.Bytes())
output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes())
@@ -203,7 +204,7 @@ func (task *ExecutionTask) Settle() {
task.result.FeeTipped,
task.result.SenderInitBalance,
- coinbaseBalance,
+ coinbaseBalance.ToBig(),
output1.Sub(output1, task.result.FeeTipped),
output2.Add(output2, task.result.FeeTipped),
)
diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go
index 17274ec1ee..b7a2a971eb 100644
--- a/core/rawdb/accessors_trie.go
+++ b/core/rawdb/accessors_trie.go
@@ -298,6 +298,11 @@ func ReadStateScheme(db ethdb.Reader) string {
if len(blob) != 0 {
return PathScheme
}
+ // The root node might be deleted during the initial snap sync, check
+ // the persistent state id then.
+ if id := ReadPersistentStateID(db); id != 0 {
+ return PathScheme
+ }
// In a hash-based scheme, the genesis state is consistently stored
// on the disk. To assess the scheme of the persistent state, it
// suffices to inspect the scheme of the genesis state.
diff --git a/core/rawdb/ancient_scheme.go b/core/rawdb/ancient_scheme.go
index d53f25b10c..61ddfced6e 100644
--- a/core/rawdb/ancient_scheme.go
+++ b/core/rawdb/ancient_scheme.go
@@ -69,14 +69,14 @@ var stateFreezerNoSnappy = map[string]bool{
// The list of identifiers of ancient stores.
var (
- chainFreezerName = "chain" // the folder name of chain segment ancient store.
- stateFreezerName = "state" // the folder name of reverse diff ancient store.
+ ChainFreezerName = "chain" // the folder name of chain segment ancient store.
+ StateFreezerName = "state" // the folder name of reverse diff ancient store.
)
// freezers the collections of all builtin freezers.
-var freezers = []string{chainFreezerName, stateFreezerName}
+var freezers = []string{ChainFreezerName, StateFreezerName}
// NewStateFreezer initializes the freezer for state history.
func NewStateFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) {
- return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
+ return NewResettableFreezer(filepath.Join(ancientDir, StateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
}
diff --git a/core/rawdb/ancient_utils.go b/core/rawdb/ancient_utils.go
index 9d71b958d4..2add85b0ec 100644
--- a/core/rawdb/ancient_utils.go
+++ b/core/rawdb/ancient_utils.go
@@ -83,14 +83,14 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
for _, freezer := range freezers {
switch freezer {
- case chainFreezerName:
- info, err := inspect(chainFreezerName, chainFreezerNoSnappy, db)
+ case ChainFreezerName:
+ info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db)
if err != nil {
return nil, err
}
infos = append(infos, info)
- case stateFreezerName:
+ case StateFreezerName:
if ReadStateScheme(db) != PathScheme {
continue
}
@@ -104,7 +104,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
}
defer f.Close()
- info, err := inspect(stateFreezerName, stateFreezerNoSnappy, f)
+ info, err := inspect(StateFreezerName, stateFreezerNoSnappy, f)
if err != nil {
return nil, err
}
@@ -129,9 +129,9 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
)
switch freezerName {
- case chainFreezerName:
+ case ChainFreezerName:
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
- case stateFreezerName:
+ case StateFreezerName:
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
default:
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go
index 4114c8a9dd..7b3910d83e 100644
--- a/core/rawdb/chain_freezer.go
+++ b/core/rawdb/chain_freezer.go
@@ -144,7 +144,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
continue
case *number < threshold:
- log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", threshold)
+ log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold)
backoff = true
diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go
index ecb801a3b8..dede764200 100644
--- a/core/rawdb/chain_iterator.go
+++ b/core/rawdb/chain_iterator.go
@@ -205,11 +205,8 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- // adjust range boundary for pruned block
- if offset := db.AncientOffSet(); offset > from {
- from = offset
- }
+func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
+
// short circuit for invalid range
if from >= to {
return
@@ -220,13 +217,13 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
batch = db.NewBatch()
start = time.Now()
logged = start.Add(-7 * time.Second)
+
// Since we iterate in reverse, we expect the first number to come
// in to be [to-1]. Therefore, setting lastNum to means that the
- // prqueue gap-evaluation will work correctly
- lastNum = to
- queue = prque.New[int64, *blockTxHashes](nil)
- // for stats reporting
- blocks, txs = 0, 0
+ // queue gap-evaluation will work correctly
+ lastNum = to
+ queue = prque.New[int64, *blockTxHashes](nil)
+ blocks, txs = 0, 0 // for stats reporting
)
for chanDelivery := range hashesCh {
@@ -278,11 +275,15 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
log.Crit("Failed writing batch to db", "error", err)
return
}
+ logger := log.Debug
+ if report {
+ logger = log.Info
+ }
select {
case <-interrupt:
- log.Debug("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
default:
- log.Debug("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
@@ -295,24 +296,21 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
- indexTransactions(db, from, to, interrupt, nil)
+func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
+ indexTransactions(db, from, to, interrupt, nil, report)
}
// indexTransactionsForTesting is the internal debug version with an additional hook.
func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- indexTransactions(db, from, to, interrupt, hook)
+ indexTransactions(db, from, to, interrupt, hook, false)
}
// unindexTransactions removes txlookup indices of the specified block range.
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- // adjust range boundary for pruned block
- if offset := db.AncientOffSet(); offset > from {
- from = offset
- }
+func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
+
// short circuit for invalid range
if from >= to {
return
@@ -323,12 +321,12 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
batch = db.NewBatch()
start = time.Now()
logged = start.Add(-7 * time.Second)
+
// we expect the first number to come in to be [from]. Therefore, setting
- // nextNum to from means that the prqueue gap-evaluation will work correctly
- nextNum = from
- queue = prque.New[int64, *blockTxHashes](nil)
- // for stats reporting
- blocks, txs = 0, 0
+ // nextNum to from means that the queue gap-evaluation will work correctly
+ nextNum = from
+ queue = prque.New[int64, *blockTxHashes](nil)
+ blocks, txs = 0, 0 // for stats reporting
)
// Otherwise spin up the concurrent iterator and unindexer
for delivery := range hashesCh {
@@ -380,11 +378,15 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
log.Crit("Failed writing batch to db", "error", err)
return
}
+ logger := log.Debug
+ if report {
+ logger = log.Info
+ }
select {
case <-interrupt:
- log.Debug("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
default:
- log.Debug("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
@@ -393,11 +395,11 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
- unindexTransactions(db, from, to, interrupt, nil)
+func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
+ unindexTransactions(db, from, to, interrupt, nil, report)
}
// unindexTransactionsForTesting is the internal debug version with an additional hook.
func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- unindexTransactions(db, from, to, interrupt, hook)
+ unindexTransactions(db, from, to, interrupt, hook, false)
}
diff --git a/core/rawdb/chain_iterator_test.go b/core/rawdb/chain_iterator_test.go
index 674365e82c..eabce3e63d 100644
--- a/core/rawdb/chain_iterator_test.go
+++ b/core/rawdb/chain_iterator_test.go
@@ -177,19 +177,18 @@ func TestIndexTransactions(t *testing.T) {
t.Fatalf("Transaction tail mismatch")
}
}
-
- IndexTransactions(chainDb, 5, 11, nil)
+ IndexTransactions(chainDb, 5, 11, nil, false)
verify(5, 11, true, 5)
verify(0, 5, false, 5)
- IndexTransactions(chainDb, 0, 5, nil)
+ IndexTransactions(chainDb, 0, 5, nil, false)
verify(0, 11, true, 0)
- UnindexTransactions(chainDb, 0, 5, nil)
+ UnindexTransactions(chainDb, 0, 5, nil, false)
verify(5, 11, true, 5)
verify(0, 5, false, 5)
- UnindexTransactions(chainDb, 5, 11, nil)
+ UnindexTransactions(chainDb, 5, 11, nil, false)
verify(0, 11, false, 11)
// Testing corner cases
@@ -210,7 +209,7 @@ func TestIndexTransactions(t *testing.T) {
})
verify(9, 11, true, 9)
verify(0, 9, false, 9)
- IndexTransactions(chainDb, 0, 9, nil)
+ IndexTransactions(chainDb, 0, 9, nil, false)
signal = make(chan struct{})
diff --git a/core/rawdb/database.go b/core/rawdb/database.go
index 3762a4366f..e882218315 100644
--- a/core/rawdb/database.go
+++ b/core/rawdb/database.go
@@ -238,7 +238,7 @@ func resolveChainFreezerDir(ancient string) string {
// sub folder, if not then two possibilities:
// - chain freezer is not initialized
// - chain freezer exists in legacy location (root ancient folder)
- freezer := path.Join(ancient, chainFreezerName)
+ freezer := path.Join(ancient, ChainFreezerName)
if !common.FileExist(freezer) {
if !common.FileExist(ancient) {
// The entire ancient store is not initialized, still use the sub
@@ -845,7 +845,6 @@ func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
{"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))},
{"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))},
{"txIndexTail", pp(ReadTxIndexTail(db))},
- {"fastTxLookupLimit", pp(ReadFastTxLookupLimit(db))},
}
if b := ReadSkeletonSyncStatus(db); b != nil {
data = append(data, []string{"SkeletonSyncStatus", string(b)})
diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go
index 0e42e31017..3c5e2f2624 100644
--- a/core/rawdb/freezer_table.go
+++ b/core/rawdb/freezer_table.go
@@ -502,6 +502,20 @@ func (t *freezerTable) truncateHead(items uint64) error {
return nil
}
+// sizeHidden returns the total data size of hidden items in the freezer table.
+// This function assumes the lock is already held.
+func (t *freezerTable) sizeHidden() (uint64, error) {
+ hidden, offset := t.itemHidden.Load(), t.itemOffset.Load()
+ if hidden <= offset {
+ return 0, nil
+ }
+ indices, err := t.getIndices(hidden-1, 1)
+ if err != nil {
+ return 0, err
+ }
+ return uint64(indices[1].offset), nil
+}
+
// truncateTail discards any recent data before the provided threshold number.
func (t *freezerTable) truncateTail(items uint64) error {
t.lock.Lock()
@@ -534,6 +548,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
newTail.unmarshalBinary(buffer)
newTailId = newTail.filenum
}
+ // Save the old size for metrics tracking. This needs to be done
+ // before any updates to either itemHidden or itemOffset.
+ oldSize, err := t.sizeNolock()
+ if err != nil {
+ return err
+ }
// Update the virtual tail marker and hidden these entries in table.
t.itemHidden.Store(items)
@@ -549,19 +569,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
if t.tailId > newTailId {
return fmt.Errorf("invalid index, tail-file %d, item-file %d", t.tailId, newTailId)
}
- // Hidden items exceed the current tail file, drop the relevant
- // data files. We need to truncate, save the old size for metrics
- // tracking.
- oldSize, err := t.sizeNolock()
- if err != nil {
- return err
- }
// Count how many items can be deleted from the file.
var (
newDeleted = items
deleted = t.itemOffset.Load()
)
-
+ // Hidden items exceed the current tail file, drop the relevant data files.
for current := items - 1; current >= deleted; current -= 1 {
if _, err := t.index.ReadAt(buffer, int64((current-deleted+1)*indexEntrySize)); err != nil {
return err
@@ -737,6 +750,7 @@ func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) {
func (t *freezerTable) getIndices(from, count uint64) ([]*indexEntry, error) {
// Apply the table-offset
from = from - t.itemOffset.Load()
+
// For reading N items, we need N+1 indices.
buffer := make([]byte, (count+1)*indexEntrySize)
if _, err := t.index.ReadAt(buffer, int64(from*indexEntrySize)); err != nil {
@@ -946,15 +960,19 @@ func (t *freezerTable) size() (uint64, error) {
return t.sizeNolock()
}
-// sizeNolock returns the total data size in the freezer table without obtaining
-// the mutex first.
+// sizeNolock returns the total data size in the freezer table. This function
+// assumes the lock is already held.
func (t *freezerTable) sizeNolock() (uint64, error) {
stat, err := t.index.Stat()
if err != nil {
return 0, err
}
+ hidden, err := t.sizeHidden()
+ if err != nil {
+ return 0, err
+ }
- total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size())
+ total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size()) - hidden
return total, nil
}
diff --git a/core/rawdb/freezer_table_test.go b/core/rawdb/freezer_table_test.go
index d54f29c56b..f951df88ed 100644
--- a/core/rawdb/freezer_table_test.go
+++ b/core/rawdb/freezer_table_test.go
@@ -705,6 +705,13 @@ func TestFreezerOffset(t *testing.T) {
}
}
+func assertTableSize(t *testing.T, f *freezerTable, size int) {
+ t.Helper()
+ if got, err := f.size(); got != uint64(size) {
+ t.Fatalf("expected size of %d bytes, got %d, err: %v", size, got, err)
+ }
+}
+
func TestTruncateTail(t *testing.T) {
t.Parallel()
@@ -740,6 +747,9 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ // maxFileSize*fileCount + headBytes + indexFileSize - hiddenBytes
+ expected := 20*7 + 48 - 0
+ assertTableSize(t, f, expected)
// truncate single element( item 0 ), deletion is only supported at file level
f.truncateTail(1)
@@ -755,6 +765,8 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ expected = 20*7 + 48 - 20
+ assertTableSize(t, f, expected)
// Reopen the table, the deletion information should be persisted as well
f.Close()
@@ -789,6 +801,8 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ expected = 20*5 + 36 - 0
+ assertTableSize(t, f, expected)
// Reopen the table, the above testing should still pass
f.Close()
@@ -812,6 +826,23 @@ func TestTruncateTail(t *testing.T) {
6: getChunk(20, 0x11),
})
+ // truncate 3 more elements( item 2, 3, 4), the file 1 should be deleted
+ // file 2 should only contain item 5
+ f.truncateTail(5)
+ checkRetrieveError(t, f, map[uint64]error{
+ 0: errOutOfBounds,
+ 1: errOutOfBounds,
+ 2: errOutOfBounds,
+ 3: errOutOfBounds,
+ 4: errOutOfBounds,
+ })
+ checkRetrieve(t, f, map[uint64][]byte{
+ 5: getChunk(20, 0xaa),
+ 6: getChunk(20, 0x11),
+ })
+ expected = 20*3 + 24 - 20
+ assertTableSize(t, f, expected)
+
// truncate all, the entire freezer should be deleted
f.truncateTail(7)
checkRetrieveError(t, f, map[uint64]error{
@@ -823,6 +854,8 @@ func TestTruncateTail(t *testing.T) {
5: errOutOfBounds,
6: errOutOfBounds,
})
+ expected = 12
+ assertTableSize(t, f, expected)
}
func TestTruncateHead(t *testing.T) {
diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go
index a3ddd11d12..59a3a43f00 100644
--- a/core/rawdb/schema.go
+++ b/core/rawdb/schema.go
@@ -80,6 +80,8 @@ var (
txIndexTailKey = []byte("TransactionIndexTail")
// fastTxLookupLimitKey tracks the transaction lookup limit during fast sync.
+ // This flag is deprecated, it's kept to avoid reporting errors when inspect
+ // database.
fastTxLookupLimitKey = []byte("FastTransactionLookupLimit")
// offset of the new updated ancientDB.
diff --git a/core/rlp_test.go b/core/rlp_test.go
index 06a1dcbc98..7ac1ef17a3 100644
--- a/core/rlp_test.go
+++ b/core/rlp_test.go
@@ -41,7 +41,7 @@ func getBlock(transactions int, uncles int, dataSize int) *types.Block {
funds = big.NewInt(1_000_000_000_000_000_000)
gspec = &Genesis{
Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Alloc: types.GenesisAlloc{address: {Balance: funds}},
}
)
// We need to generate as many blocks +1 as uncles
diff --git a/core/state/database.go b/core/state/database.go
index c4b0c5f7e5..9cfb1d1221 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/ethereum/go-ethereum/triedb"
)
const (
@@ -67,7 +68,7 @@ type Database interface {
DiskDB() ethdb.KeyValueStore
// TrieDB returns the underlying trie database for managing trie nodes.
- TrieDB() *trie.Database
+ TrieDB() *triedb.Database
}
// Trie is a Ethereum Merkle Patricia trie.
@@ -150,17 +151,17 @@ func NewDatabase(db ethdb.Database) Database {
// NewDatabaseWithConfig creates a backing store for state. The returned database
// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
// large memory cache.
-func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
+func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database {
return &cachingDB{
disk: db,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
- triedb: trie.NewDatabase(db, config),
+ triedb: triedb.NewDatabase(db, config),
}
}
// NewDatabaseWithNodeDB creates a state database with an already initialized node database.
-func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.Database) Database {
+func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database {
return &cachingDB{
disk: db,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
@@ -173,7 +174,7 @@ type cachingDB struct {
disk ethdb.KeyValueStore
codeSizeCache *lru.Cache[common.Hash, int]
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
- triedb *trie.Database
+ triedb *triedb.Database
}
// OpenTrie opens the main account trie at a specific root hash.
@@ -270,6 +271,6 @@ func (db *cachingDB) DiskDB() ethdb.KeyValueStore {
}
// TrieDB retrieves any intermediate trie-node caching layer.
-func (db *cachingDB) TrieDB() *trie.Database {
+func (db *cachingDB) TrieDB() *triedb.Database {
return db.triedb
}
diff --git a/core/state/journal.go b/core/state/journal.go
index 3b1ecdef6d..5927a963e6 100644
--- a/core/state/journal.go
+++ b/core/state/journal.go
@@ -17,10 +17,9 @@
package state
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/blockstm"
+ "github.com/holiman/uint256"
)
// journalEntry is a modification entry in the state change journal that can be
@@ -105,13 +104,13 @@ type (
selfDestructChange struct {
account *common.Address
prev bool // whether account had already self-destructed
- prevbalance *big.Int
+ prevbalance *uint256.Int
}
// Changes to individual accounts.
balanceChange struct {
account *common.Address
- prev *big.Int
+ prev *uint256.Int
}
nonceChange struct {
account *common.Address
diff --git a/core/state/pruner/bloom.go b/core/state/pruner/bloom.go
index 525b8eaf68..6d595cb5dc 100644
--- a/core/state/pruner/bloom.go
+++ b/core/state/pruner/bloom.go
@@ -27,17 +27,10 @@ import (
bloomfilter "github.com/holiman/bloomfilter/v2"
)
-// stateBloomHasher is a wrapper around a byte blob to satisfy the interface API
-// requirements of the bloom library used. It's used to convert a trie hash or
-// contract code hash into a 64 bit mini hash.
-type stateBloomHasher []byte
-
-func (f stateBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (f stateBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (f stateBloomHasher) Reset() { panic("not implemented") }
-func (f stateBloomHasher) BlockSize() int { panic("not implemented") }
-func (f stateBloomHasher) Size() int { return 8 }
-func (f stateBloomHasher) Sum64() uint64 { return binary.BigEndian.Uint64(f) }
+// stateBloomHash is used to convert a trie hash or contract code hash into a 64 bit mini hash.
+func stateBloomHash(f []byte) uint64 {
+ return binary.BigEndian.Uint64(f)
+}
// stateBloom is a bloom filter used during the state conversion(snapshot->state).
// The keys of all generated entries will be recorded here so that in the pruning
@@ -118,13 +111,12 @@ func (bloom *stateBloom) Put(key []byte, value []byte) error {
if !isCode {
return errors.New("invalid entry")
}
-
- bloom.bloom.Add(stateBloomHasher(codeKey))
+ bloom.bloom.AddHash(stateBloomHash(codeKey))
return nil
}
- bloom.bloom.Add(stateBloomHasher(key))
+ bloom.bloom.AddHash(stateBloomHash(key))
return nil
}
@@ -137,5 +129,5 @@ func (bloom *stateBloom) Delete(key []byte) error { panic("not supported") }
// - If it says yes, the key may be contained
// - If it says no, the key is definitely not contained.
func (bloom *stateBloom) Contain(key []byte) bool {
- return bloom.bloom.Contains(stateBloomHasher(key))
+ return bloom.bloom.ContainsHash(stateBloomHash(key))
}
diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go
index abbc0044a6..f1f74942e0 100644
--- a/core/state/pruner/pruner.go
+++ b/core/state/pruner/pruner.go
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/prometheus/tsdb/fileutil"
)
@@ -90,7 +91,7 @@ func NewPruner(db ethdb.Database, config Config) (*Pruner, error) {
return nil, errors.New("failed to load head block")
}
// Offline pruning is only supported in legacy hash based scheme.
- triedb := trie.NewDatabase(db, trie.HashDefaults)
+ triedb := triedb.NewDatabase(db, triedb.HashDefaults)
snapconfig := snapshot.Config{
CacheSize: 256,
@@ -603,7 +604,7 @@ func RecoverPruning(datadir string, db ethdb.Database) error {
AsyncBuild: false,
}
// Offline pruning is only supported in legacy hash based scheme.
- triedb := trie.NewDatabase(db, trie.HashDefaults)
+ triedb := triedb.NewDatabase(db, triedb.HashDefaults)
snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root())
if err != nil {
return err // The relevant snapshot(s) might not exist
@@ -646,7 +647,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
if genesis == nil {
return errors.New("missing genesis block")
}
- t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), trie.NewDatabase(db, trie.HashDefaults))
+ t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), triedb.NewDatabase(db, triedb.HashDefaults))
if err != nil {
return err
}
@@ -670,7 +671,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
}
if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root)
- storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db, trie.HashDefaults))
+ storageTrie, err := trie.NewStateTrie(id, triedb.NewDatabase(db, triedb.HashDefaults))
if err != nil {
return err
}
diff --git a/core/state/snapshot/conversion.go b/core/state/snapshot/conversion.go
index 8a1715a9b7..0597464ccc 100644
--- a/core/state/snapshot/conversion.go
+++ b/core/state/snapshot/conversion.go
@@ -389,15 +389,15 @@ func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, accou
}
func stackTrieGenerate(db ethdb.KeyValueWriter, scheme string, owner common.Hash, in chan trieKV, out chan common.Hash) {
- options := trie.NewStackTrieOptions()
+ var onTrieNode trie.OnTrieNode
if db != nil {
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ onTrieNode = func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(db, owner, path, hash, blob, scheme)
- })
+ }
}
- t := trie.NewStackTrie(options)
+ t := trie.NewStackTrie(onTrieNode)
for leaf := range in {
_ = t.Update(leaf.key[:], leaf.value)
}
- out <- t.Commit()
+ out <- t.Hash()
}
diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go
index 76fce22d1c..f7ef3418b5 100644
--- a/core/state/snapshot/difflayer.go
+++ b/core/state/snapshot/difflayer.go
@@ -124,47 +124,20 @@ type diffLayer struct {
lock sync.RWMutex
}
-// destructBloomHasher is a wrapper around a common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert a destruct
-// event into a 64 bit mini hash.
-type destructBloomHasher common.Hash
-
-func (h destructBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h destructBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h destructBloomHasher) Reset() { panic("not implemented") }
-func (h destructBloomHasher) BlockSize() int { panic("not implemented") }
-func (h destructBloomHasher) Size() int { return 8 }
-func (h destructBloomHasher) Sum64() uint64 {
+// destructBloomHash is used to convert a destruct event into a 64 bit mini hash.
+func destructBloomHash(h common.Hash) uint64 {
return binary.BigEndian.Uint64(h[bloomDestructHasherOffset : bloomDestructHasherOffset+8])
}
-// accountBloomHasher is a wrapper around a common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert an account
-// hash into a 64 bit mini hash.
-type accountBloomHasher common.Hash
-
-func (h accountBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h accountBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h accountBloomHasher) Reset() { panic("not implemented") }
-func (h accountBloomHasher) BlockSize() int { panic("not implemented") }
-func (h accountBloomHasher) Size() int { return 8 }
-func (h accountBloomHasher) Sum64() uint64 {
+// accountBloomHash is used to convert an account hash into a 64 bit mini hash.
+func accountBloomHash(h common.Hash) uint64 {
return binary.BigEndian.Uint64(h[bloomAccountHasherOffset : bloomAccountHasherOffset+8])
}
-// storageBloomHasher is a wrapper around a [2]common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert an account
-// hash into a 64 bit mini hash.
-type storageBloomHasher [2]common.Hash
-
-func (h storageBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h storageBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h storageBloomHasher) Reset() { panic("not implemented") }
-func (h storageBloomHasher) BlockSize() int { panic("not implemented") }
-func (h storageBloomHasher) Size() int { return 8 }
-func (h storageBloomHasher) Sum64() uint64 {
- return binary.BigEndian.Uint64(h[0][bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
- binary.BigEndian.Uint64(h[1][bloomStorageHasherOffset:bloomStorageHasherOffset+8])
+// storageBloomHash is used to convert an account hash and a storage hash into a 64 bit mini hash.
+func storageBloomHash(h0, h1 common.Hash) uint64 {
+ return binary.BigEndian.Uint64(h0[bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
+ binary.BigEndian.Uint64(h1[bloomStorageHasherOffset:bloomStorageHasherOffset+8])
}
// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low
@@ -236,16 +209,16 @@ func (dl *diffLayer) rebloom(origin *diskLayer) {
}
// Iterate over all the accounts and storage slots and index them
for hash := range dl.destructSet {
- dl.diffed.Add(destructBloomHasher(hash))
+ dl.diffed.AddHash(destructBloomHash(hash))
}
for hash := range dl.accountData {
- dl.diffed.Add(accountBloomHasher(hash))
+ dl.diffed.AddHash(accountBloomHash(hash))
}
for accountHash, slots := range dl.storageData {
for storageHash := range slots {
- dl.diffed.Add(storageBloomHasher{accountHash, storageHash})
+ dl.diffed.AddHash(storageBloomHash(accountHash, storageHash))
}
}
// Calculate the current false positive rate and update the error rate meter.
@@ -308,9 +281,9 @@ func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) {
}
// Check the bloom filter first whether there's even a point in reaching into
// all the maps in all the layers below
- hit := dl.diffed.Contains(accountBloomHasher(hash))
+ hit := dl.diffed.ContainsHash(accountBloomHash(hash))
if !hit {
- hit = dl.diffed.Contains(destructBloomHasher(hash))
+ hit = dl.diffed.ContainsHash(destructBloomHash(hash))
}
var origin *diskLayer
@@ -383,9 +356,9 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
dl.lock.RUnlock()
return nil, ErrSnapshotStale
}
- hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash})
+ hit := dl.diffed.ContainsHash(storageBloomHash(accountHash, storageHash))
if !hit {
- hit = dl.diffed.Contains(destructBloomHasher(accountHash))
+ hit = dl.diffed.ContainsHash(destructBloomHash(accountHash))
}
var origin *diskLayer
diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go
index bcad1ba41c..ea4755cc4b 100644
--- a/core/state/snapshot/disklayer.go
+++ b/core/state/snapshot/disklayer.go
@@ -26,13 +26,13 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// diskLayer is a low level persistent snapshot built on top of a key-value store.
type diskLayer struct {
diskdb ethdb.KeyValueStore // Key-value store containing the base snapshot
- triedb *trie.Database // Trie node cache for reconstruction purposes
+ triedb *triedb.Database // Trie node cache for reconstruction purposes
cache *fastcache.Cache // Cache to avoid hitting the disk for direct access
root common.Hash // Root hash of the base snapshot
diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go
index 8df6d4a36e..e88026c89b 100644
--- a/core/state/snapshot/generate.go
+++ b/core/state/snapshot/generate.go
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -55,7 +56,7 @@ var (
// generateSnapshot regenerates a brand new snapshot based on an existing state
// database and head block asynchronously. The snapshot is returned immediately
// and generation is continued in the background until done.
-func generateSnapshot(diskdb ethdb.KeyValueStore, triedb *trie.Database, cache int, root common.Hash) *diskLayer {
+func generateSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, cache int, root common.Hash) *diskLayer {
// Create a new disk layer with an initialized state marker at zero
var (
stats = &generatorStats{start: time.Now()}
@@ -379,7 +380,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
if len(result.keys) > 0 {
mdb := rawdb.NewMemoryDatabase()
- tdb := trie.NewDatabase(mdb, trie.HashDefaults)
+ tdb := triedb.NewDatabase(mdb, triedb.HashDefaults)
defer tdb.Close()
snapTrie := trie.NewEmpty(tdb)
for i, key := range result.keys {
diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go
index ddf5e688fd..190f6320fa 100644
--- a/core/state/snapshot/generate_test.go
+++ b/core/state/snapshot/generate_test.go
@@ -18,7 +18,6 @@ package snapshot
import (
"fmt"
- "math/big"
"os"
"testing"
"time"
@@ -30,9 +29,11 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -61,9 +62,9 @@ func testGeneration(t *testing.T, scheme string) {
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
@@ -100,16 +101,16 @@ func testGenerateExistentState(t *testing.T, scheme string) {
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
root, snap := helper.CommitAndGenerate()
@@ -161,20 +162,20 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
type testHelper struct {
diskdb ethdb.Database
- triedb *trie.Database
+ triedb *triedb.Database
accTrie *trie.StateTrie
nodes *trienode.MergedNodeSet
}
func newHelper(scheme string) *testHelper {
diskdb := rawdb.NewMemoryDatabase()
- config := &trie.Config{}
+ config := &triedb.Config{}
if scheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{} // disable caching
} else {
config.HashDB = &hashdb.Config{} // disable caching
}
- triedb := trie.NewDatabase(diskdb, config)
+ triedb := triedb.NewDatabase(diskdb, config)
accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), triedb)
return &testHelper{
diskdb: diskdb,
@@ -267,28 +268,28 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
helper := newHelper(scheme)
// Account one, empty root but non-empty database
- helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
// Account two, non empty root but empty database
stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
// Miss slots
{
// Account three, non empty root but misses slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
// Account four, non empty root but misses slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
// Account five, non empty root but misses slots in the end
helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
}
@@ -296,22 +297,22 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// Account six, non empty root but wrong slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
// Account seven, non empty root but wrong slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
// Account eight, non empty root but wrong slots in the end
helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-8", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
// Account 9, non empty root but rotated slots
helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-9", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
}
@@ -319,17 +320,17 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// Account 10, non empty root but extra slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-10", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
// Account 11, non empty root but extra slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-11", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
// Account 12, non empty root but extra slots in the end
helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-12", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
}
@@ -374,25 +375,25 @@ func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) {
// Missing accounts, only in the trie
{
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
- helper.addTrieAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
- helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
+ helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
+ helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
}
// Wrong accounts
{
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
}
// Extra accounts, only in the snap
{
- helper.addSnapAccount("acc-0", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning
- helper.addSnapAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle
- helper.addSnapAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
+ helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning
+ helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle
+ helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
}
root, snap := helper.CommitAndGenerate()
@@ -426,9 +427,9 @@ func testGenerateCorruptAccountTrie(t *testing.T, scheme string) {
// without any storage slots to keep the test smaller.
helper := newHelper(scheme)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
@@ -470,11 +471,11 @@ func testGenerateMissingStorageTrie(t *testing.T, scheme string) {
acc3 = hashData([]byte("acc-3"))
helper = newHelper(scheme)
)
- stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit()
@@ -510,11 +511,11 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) {
// two of which also has the same 3-slot storage trie attached.
helper := newHelper(scheme)
- stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit()
@@ -554,7 +555,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@@ -574,7 +575,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte("acc-2"))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@@ -632,7 +633,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@@ -646,7 +647,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
{
// 100 accounts exist only in snapshot
for i := 0; i < 1000; i++ {
- acc := &types.StateAccount{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@@ -690,7 +691,7 @@ func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) {
}
helper := newHelper(scheme)
{
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val)
@@ -734,7 +735,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) {
}
helper := newHelper(scheme)
{
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
@@ -779,7 +780,7 @@ func testGenerateFromEmptySnap(t *testing.T, scheme string) {
for i := 0; i < 400; i++ {
stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
- &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
}
root, snap := helper.CommitAndGenerate()
@@ -822,7 +823,7 @@ func testGenerateWithIncompleteStorage(t *testing.T, scheme string) {
for i := 0; i < 8; i++ {
accKey := fmt.Sprintf("acc-%d", i)
stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true)
- helper.addAccount(accKey, &types.StateAccount{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
var moddedKeys []string
var moddedVals []string
@@ -924,11 +925,11 @@ func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
@@ -964,11 +965,11 @@ func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string)
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
populateDangling(helper.diskdb)
diff --git a/core/state/snapshot/journal.go b/core/state/snapshot/journal.go
index 1efee13799..4c1f7dfd22 100644
--- a/core/state/snapshot/journal.go
+++ b/core/state/snapshot/journal.go
@@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
const journalVersion uint64 = 0
@@ -126,7 +126,7 @@ func loadAndParseJournal(db ethdb.KeyValueStore, base *diskLayer) (snapshot, jou
}
// loadSnapshot loads a pre-existing state snapshot backed by a key-value store.
-func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *trie.Database, root common.Hash, cache int, recovery bool, noBuild bool) (snapshot, bool, error) {
+func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash, cache int, recovery bool, noBuild bool) (snapshot, bool, error) {
// If snapshotting is disabled (initial sync in progress), don't do anything,
// wait for the chain to permit us to do something meaningful
if rawdb.ReadSnapshotDisabled(diskdb) {
diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go
index 0c5b87182f..68c4a5f034 100644
--- a/core/state/snapshot/snapshot.go
+++ b/core/state/snapshot/snapshot.go
@@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -168,7 +168,7 @@ type Config struct {
type Tree struct {
config Config // Snapshots configurations
diskdb ethdb.KeyValueStore // Persistent database to store the snapshot
- triedb *trie.Database // In-memory cache to access the trie through
+ triedb *triedb.Database // In-memory cache to access the trie through
layers map[common.Hash]snapshot // Collection of all known layers
lock sync.RWMutex
@@ -192,7 +192,7 @@ type Tree struct {
// state trie.
// - otherwise, the entire snapshot is considered invalid and will be recreated on
// a background thread.
-func New(config Config, diskdb ethdb.KeyValueStore, triedb *trie.Database, root common.Hash) (*Tree, error) {
+func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash) (*Tree, error) {
// Create a new, empty snapshot tree
snap := &Tree{
config: config,
@@ -262,6 +262,14 @@ func (t *Tree) Disable() {
for _, layer := range t.layers {
switch layer := layer.(type) {
case *diskLayer:
+
+ layer.lock.RLock()
+ generating := layer.genMarker != nil
+ layer.lock.RUnlock()
+ if !generating {
+ // Generator is already aborted or finished
+ break
+ }
// If the base layer is generating, abort it
if layer.genAbort != nil {
abort := make(chan *generatorStats)
diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go
index 5656288d78..964a6b2d84 100644
--- a/core/state/snapshot/snapshot_test.go
+++ b/core/state/snapshot/snapshot_test.go
@@ -20,7 +20,6 @@ import (
crand "crypto/rand"
"encoding/binary"
"fmt"
- "math/big"
"math/rand"
"testing"
"time"
@@ -30,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/holiman/uint256"
)
// randomHash generates a random blob of data and returns it as a hash.
@@ -45,7 +45,7 @@ func randomHash() common.Hash {
// randomAccount generates a random account and returns it RLP encoded.
func randomAccount() []byte {
a := &types.StateAccount{
- Balance: big.NewInt(rand.Int63()),
+ Balance: uint256.NewInt(rand.Uint64()),
Nonce: rand.Uint64(),
Root: randomHash(),
CodeHash: types.EmptyCodeHash[:],
diff --git a/core/state/state_object.go b/core/state/state_object.go
index 5bba1482db..cd3e09d263 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -20,7 +20,6 @@ import (
"bytes"
"fmt"
"io"
- "math/big"
"sync"
"time"
@@ -30,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
)
type Code []byte
@@ -97,7 +97,7 @@ type stateObject struct {
// empty returns whether the account is considered empty.
func (s *stateObject) empty() bool {
- return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
+ return s.data.Nonce == 0 && s.data.Balance.IsZero() && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
}
// newObject creates a state object.
@@ -431,10 +431,10 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) {
// AddBalance adds amount to s's balance.
// It is used to add funds to the destination account of a transfer.
-func (s *stateObject) AddBalance(amount *big.Int) {
+func (s *stateObject) AddBalance(amount *uint256.Int) {
// EIP161: We must check emptiness for the objects such that the account
// clearing (0,0,0 objects) can take effect.
- if amount.Sign() == 0 {
+ if amount.IsZero() {
if s.empty() {
s.touch()
}
@@ -442,28 +442,29 @@ func (s *stateObject) AddBalance(amount *big.Int) {
return
}
- s.SetBalance(new(big.Int).Add(s.Balance(), amount))
+ s.SetBalance(new(uint256.Int).Add(s.Balance(), amount))
}
// SubBalance removes amount from s's balance.
// It is used to remove funds from the origin account of a transfer.
-func (s *stateObject) SubBalance(amount *big.Int) {
- if amount.Sign() == 0 {
+func (s *stateObject) SubBalance(amount *uint256.Int) {
+ if amount.IsZero() {
return
}
- s.SetBalance(new(big.Int).Sub(s.Balance(), amount))
+ s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount))
}
-func (s *stateObject) SetBalance(amount *big.Int) {
+func (s *stateObject) SetBalance(amount *uint256.Int) {
s.db.journal.append(balanceChange{
account: &s.address,
- prev: new(big.Int).Set(s.data.Balance),
+ prev: new(uint256.Int).Set(s.data.Balance),
})
+
s.setBalance(amount)
}
-func (s *stateObject) setBalance(amount *big.Int) {
+func (s *stateObject) setBalance(amount *uint256.Int) {
s.data.Balance = amount
}
@@ -567,7 +568,7 @@ func (s *stateObject) CodeHash() []byte {
return s.data.CodeHash
}
-func (s *stateObject) Balance() *big.Int {
+func (s *stateObject) Balance() *uint256.Int {
return s.data.Balance
}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 2f45ba44b4..9be610f962 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -19,7 +19,6 @@ package state
import (
"bytes"
"encoding/json"
- "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -27,7 +26,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
)
type stateEnv struct {
@@ -43,17 +43,17 @@ func newStateEnv() *stateEnv {
func TestDump(t *testing.T) {
db := rawdb.NewMemoryDatabase()
- tdb := NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
+ tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
sdb, _ := New(types.EmptyRootHash, tdb, nil)
s := &stateEnv{db: db, state: sdb}
// generate a few entries
- obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
- obj1.AddBalance(big.NewInt(22))
- obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
+ obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
+ obj1.AddBalance(uint256.NewInt(22))
+ obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
- obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
- obj3.SetBalance(big.NewInt(44))
+ obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
+ obj3.SetBalance(uint256.NewInt(44))
// write some of them to the trie
s.state.updateStateObject(obj1)
@@ -100,19 +100,19 @@ func TestDump(t *testing.T) {
func TestIterativeDump(t *testing.T) {
db := rawdb.NewMemoryDatabase()
- tdb := NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
+ tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
sdb, _ := New(types.EmptyRootHash, tdb, nil)
s := &stateEnv{db: db, state: sdb}
// generate a few entries
- obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
- obj1.AddBalance(big.NewInt(22))
- obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
+ obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
+ obj1.AddBalance(uint256.NewInt(22))
+ obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
- obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
- obj3.SetBalance(big.NewInt(44))
- obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
- obj4.AddBalance(big.NewInt(1337))
+ obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
+ obj3.SetBalance(uint256.NewInt(44))
+ obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00}))
+ obj4.AddBalance(uint256.NewInt(1337))
// write some of them to the trie
s.state.updateStateObject(obj1)
@@ -208,7 +208,7 @@ func TestSnapshot2(t *testing.T) {
// db, trie are already non-empty values
so0 := state.getStateObject(stateobjaddr0)
- so0.SetBalance(big.NewInt(42))
+ so0.SetBalance(uint256.NewInt(42))
so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.selfDestructed = false
@@ -220,7 +220,7 @@ func TestSnapshot2(t *testing.T) {
// and one with deleted == true
so1 := state.getStateObject(stateobjaddr1)
- so1.SetBalance(big.NewInt(52))
+ so1.SetBalance(uint256.NewInt(52))
so1.SetNonce(53)
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.selfDestructed = true
diff --git a/core/state/statedb.go b/core/state/statedb.go
index e74107ba17..7ff3c9fa0b 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -19,7 +19,6 @@ package state
import (
"fmt"
- "math/big"
"sort"
"time"
@@ -35,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
const (
@@ -588,14 +588,13 @@ const CodePath = 3
const SuicidePath = 4
// GetBalance retrieves the balance from the given address or 0 if object not found
-func (s *StateDB) GetBalance(addr common.Address) *big.Int {
- return MVRead(s, blockstm.NewSubpathKey(addr, BalancePath), common.Big0, func(s *StateDB) *big.Int {
+func (s *StateDB) GetBalance(addr common.Address) *uint256.Int {
+ return MVRead(s, blockstm.NewSubpathKey(addr, BalancePath), uint256.NewInt(0), func(s *StateDB) *uint256.Int {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Balance()
}
-
- return common.Big0
+ return uint256.NewInt(0)
})
}
@@ -730,8 +729,8 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
*/
// AddBalance adds amount to the account associated with addr.
-func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if s.mvHashmap != nil {
// ensure a read balance operation is recorded in mvHashmap
@@ -746,8 +745,8 @@ func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
}
// SubBalance subtracts amount from the account associated with addr.
-func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if s.mvHashmap != nil {
// ensure a read balance operation is recorded in mvHashmap
@@ -761,8 +760,8 @@ func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
}
}
-func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject = s.mvRecordWritten(stateObject)
stateObject.SetBalance(amount)
@@ -771,7 +770,7 @@ func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
}
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject = s.mvRecordWritten(stateObject)
stateObject.SetNonce(nonce)
@@ -780,7 +779,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
}
func (s *StateDB) SetCode(addr common.Address, code []byte) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject = s.mvRecordWritten(stateObject)
stateObject.SetCode(crypto.Keccak256Hash(code), code)
@@ -789,7 +788,7 @@ func (s *StateDB) SetCode(addr common.Address, code []byte) {
}
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject = s.mvRecordWritten(stateObject)
stateObject.SetState(key, value)
@@ -812,7 +811,8 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
if _, ok := s.stateObjectsDestruct[addr]; !ok {
s.stateObjectsDestruct[addr] = nil
}
- stateObject := s.GetOrNewStateObject(addr)
+
+ stateObject := s.getOrNewStateObject(addr)
for k, v := range storage {
stateObject.SetState(k, v)
@@ -834,10 +834,10 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
s.journal.append(selfDestructChange{
account: &addr,
prev: stateObject.selfDestructed,
- prevbalance: new(big.Int).Set(stateObject.Balance()),
+ prevbalance: new(uint256.Int).Set(stateObject.Balance()),
})
stateObject.markSelfdestructed()
- stateObject.data.Balance = new(big.Int)
+ stateObject.data.Balance = new(uint256.Int)
MVWrite(s, blockstm.NewSubpathKey(addr, SuicidePath))
MVWrite(s, blockstm.NewSubpathKey(addr, BalancePath))
@@ -1030,8 +1030,8 @@ func (s *StateDB) setStateObject(object *stateObject) {
s.stateObjects[object.Address()] = object
}
-// GetOrNewStateObject retrieves a state object or create a new state object if nil.
-func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
+// getOrNewStateObject retrieves a state object or create a new state object if nil.
+func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
stateObject := s.getStateObject(addr)
if stateObject == nil {
stateObject, _ = s.createObject(addr)
@@ -1426,12 +1426,10 @@ func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (boo
nodes = trienode.NewNodeSet(addrHash)
slots = make(map[common.Hash][]byte)
)
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ stack := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
nodes.AddNode(path, trienode.NewDeleted())
size += common.StorageSize(len(path))
})
- stack := trie.NewStackTrie(options)
for iter.Next() {
if size > storageDeleteLimit {
return true, size, nil, nil, nil
diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go
index c4704257c7..b416bcf1f3 100644
--- a/core/state/statedb_fuzz_test.go
+++ b/core/state/statedb_fuzz_test.go
@@ -22,7 +22,6 @@ import (
"errors"
"fmt"
"math"
- "math/big"
"math/rand"
"reflect"
"strings"
@@ -36,8 +35,10 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
)
// A stateTest checks that the state changes are correctly captured. Instances
@@ -60,7 +61,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction
{
name: "SetBalance",
fn: func(a testAction, s *StateDB) {
- s.SetBalance(addr, big.NewInt(a.args[0]))
+ s.SetBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
@@ -181,7 +182,7 @@ func (test *stateTest) run() bool {
storageList = append(storageList, copy2DSet(states.Storages))
}
disk = rawdb.NewMemoryDatabase()
- tdb = trie.NewDatabase(disk, &trie.Config{PathDB: pathdb.Defaults})
+ tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults})
sdb = NewDatabaseWithNodeDB(disk, tdb)
byzantium = rand.Intn(2) == 0
)
@@ -252,7 +253,7 @@ func (test *stateTest) run() bool {
// - the account was indeed not present in trie
// - the account is present in new trie, nil->nil is regarded as invalid
// - the slots transition is correct
-func (test *stateTest) verifyAccountCreation(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addr common.Address, slots map[common.Hash][]byte) error {
+func (test *stateTest) verifyAccountCreation(next common.Hash, db *triedb.Database, otr, ntr *trie.Trie, addr common.Address, slots map[common.Hash][]byte) error {
// Verify account change
addrHash := crypto.Keccak256Hash(addr.Bytes())
oBlob, err := otr.Get(addrHash.Bytes())
@@ -303,7 +304,7 @@ func (test *stateTest) verifyAccountCreation(next common.Hash, db *trie.Database
// - the account was indeed present in trie
// - the account in old trie matches the provided value
// - the slots transition is correct
-func (test *stateTest) verifyAccountUpdate(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addr common.Address, origin []byte, slots map[common.Hash][]byte) error {
+func (test *stateTest) verifyAccountUpdate(next common.Hash, db *triedb.Database, otr, ntr *trie.Trie, addr common.Address, origin []byte, slots map[common.Hash][]byte) error {
// Verify account change
addrHash := crypto.Keccak256Hash(addr.Bytes())
oBlob, err := otr.Get(addrHash.Bytes())
@@ -357,7 +358,7 @@ func (test *stateTest) verifyAccountUpdate(next common.Hash, db *trie.Database,
return nil
}
-func (test *stateTest) verify(root common.Hash, next common.Hash, db *trie.Database, accountsOrigin map[common.Address][]byte, storagesOrigin map[common.Address]map[common.Hash][]byte) error {
+func (test *stateTest) verify(root common.Hash, next common.Hash, db *triedb.Database, accountsOrigin map[common.Address][]byte, storagesOrigin map[common.Address]map[common.Hash][]byte) error {
otr, err := trie.New(trie.StateTrieID(root), db)
if err != nil {
return err
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index 180dd4d2f2..645ce7c169 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -40,9 +40,10 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
"github.com/holiman/uint256"
)
@@ -52,14 +53,14 @@ func TestUpdateLeaks(t *testing.T) {
// Create an empty state database
var (
db = rawdb.NewMemoryDatabase()
- tdb = trie.NewDatabase(db, nil)
+ tdb = triedb.NewDatabase(db, nil)
)
state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil)
// Update it with some accounts
for i := byte(0); i < 255; i++ {
addr := common.BytesToAddress([]byte{i})
- state.AddBalance(addr, big.NewInt(int64(11*i)))
+ state.AddBalance(addr, uint256.NewInt(uint64(11*i)))
state.SetNonce(addr, uint64(42*i))
if i%2 == 0 {
@@ -90,13 +91,13 @@ func TestIntermediateLeaks(t *testing.T) {
// Create two state databases, one transitioning to the final state, the other final from the beginning
transDb := rawdb.NewMemoryDatabase()
finalDb := rawdb.NewMemoryDatabase()
- transNdb := trie.NewDatabase(transDb, nil)
- finalNdb := trie.NewDatabase(finalDb, nil)
+ transNdb := triedb.NewDatabase(transDb, nil)
+ finalNdb := triedb.NewDatabase(finalDb, nil)
transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil)
finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil)
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
- state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
+ state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)))
state.SetNonce(addr, uint64(42*i+tweak))
if i%2 == 0 {
@@ -177,8 +178,8 @@ func TestCopy(t *testing.T) {
orig, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
for i := byte(0); i < 255; i++ {
- obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- obj.AddBalance(big.NewInt(int64(i)))
+ obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ obj.AddBalance(uint256.NewInt(uint64(i)))
orig.updateStateObject(obj)
}
orig.Finalise(false)
@@ -191,13 +192,13 @@ func TestCopy(t *testing.T) {
// modify all in memory
for i := byte(0); i < 255; i++ {
- origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- origObj.AddBalance(big.NewInt(2 * int64(i)))
- copyObj.AddBalance(big.NewInt(3 * int64(i)))
- ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
+ origObj.AddBalance(uint256.NewInt(2 * uint64(i)))
+ copyObj.AddBalance(uint256.NewInt(3 * uint64(i)))
+ ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i)))
orig.updateStateObject(origObj)
copy.updateStateObject(copyObj)
@@ -221,19 +222,19 @@ func TestCopy(t *testing.T) {
// Verify that the three states have been updated independently
for i := byte(0); i < 255; i++ {
- origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(3 * uint64(i)); origObj.Balance().Cmp(want) != 0 {
t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
}
- if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(4 * uint64(i)); copyObj.Balance().Cmp(want) != 0 {
t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
}
- if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(5 * uint64(i)); ccopyObj.Balance().Cmp(want) != 0 {
t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
}
}
@@ -282,14 +283,14 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
{
name: "SetBalance",
fn: func(a testAction, s *StateDB) {
- s.SetBalance(addr, big.NewInt(a.args[0]))
+ s.SetBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
{
name: "AddBalance",
fn: func(a testAction, s *StateDB) {
- s.AddBalance(addr, big.NewInt(a.args[0]))
+ s.AddBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
@@ -568,12 +569,12 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
func TestTouchDelete(t *testing.T) {
s := newStateEnv()
- s.state.GetOrNewStateObject(common.Address{})
+ s.state.getOrNewStateObject(common.Address{})
root, _ := s.state.Commit(0, false)
s.state, _ = New(root, s.state.db, s.state.snaps)
snapshot := s.state.Snapshot()
- s.state.AddBalance(common.Address{}, new(big.Int))
+ s.state.AddBalance(common.Address{}, new(uint256.Int))
if len(s.state.journal.dirties) != 1 {
t.Fatal("expected one dirty state object")
@@ -605,7 +606,7 @@ func TestMVHashMapReadWriteDelete(t *testing.T) {
addr := common.HexToAddress("0x01")
key := common.HexToHash("0x01")
val := common.HexToHash("0x01")
- balance := new(big.Int).SetUint64(uint64(100))
+ balance := uint256.NewInt(100)
// Tx0 read
v := states[0].GetState(addr, key)
@@ -613,7 +614,7 @@ func TestMVHashMapReadWriteDelete(t *testing.T) {
assert.Equal(t, common.Hash{}, v)
// Tx1 write
- states[1].GetOrNewStateObject(addr)
+ states[1].getOrNewStateObject(addr)
states[1].SetState(addr, key, val)
states[1].SetBalance(addr, balance)
states[1].FlushMVWriteSet()
@@ -672,17 +673,17 @@ func TestMVHashMapRevert(t *testing.T) {
addr := common.HexToAddress("0x01")
key := common.HexToHash("0x01")
val := common.HexToHash("0x01")
- balance := new(big.Int).SetUint64(uint64(100))
+ balance := uint256.NewInt(100)
// Tx0 write
- states[0].GetOrNewStateObject(addr)
+ states[0].getOrNewStateObject(addr)
states[0].SetState(addr, key, val)
states[0].SetBalance(addr, balance)
states[0].FlushMVWriteSet()
// Tx1 perform some ops and then revert
snapshot := states[1].Snapshot()
- states[1].AddBalance(addr, new(big.Int).SetUint64(uint64(100)))
+ states[1].AddBalance(addr, uint256.NewInt(100))
states[1].SetState(addr, key, common.HexToHash("0x02"))
v := states[1].GetState(addr, key)
b := states[1].GetBalance(addr)
@@ -728,7 +729,7 @@ func TestMVHashMapMarkEstimate(t *testing.T) {
addr := common.HexToAddress("0x01")
key := common.HexToHash("0x01")
val := common.HexToHash("0x01")
- balance := new(big.Int).SetUint64(uint64(100))
+ balance := uint256.NewInt(100)
// Tx0 read
v := states[0].GetState(addr, key)
@@ -741,7 +742,7 @@ func TestMVHashMapMarkEstimate(t *testing.T) {
states[0].FlushMVWriteSet()
// Tx1 write
- states[1].GetOrNewStateObject(addr)
+ states[1].getOrNewStateObject(addr)
states[1].SetState(addr, key, val)
states[1].SetBalance(addr, balance)
states[1].FlushMVWriteSet()
@@ -794,12 +795,12 @@ func TestMVHashMapOverwrite(t *testing.T) {
addr := common.HexToAddress("0x01")
key := common.HexToHash("0x01")
val1 := common.HexToHash("0x01")
- balance1 := new(big.Int).SetUint64(uint64(100))
+ balance1 := uint256.NewInt(100)
val2 := common.HexToHash("0x02")
- balance2 := new(big.Int).SetUint64(uint64(200))
+ balance2 := uint256.NewInt(200)
// Tx0 write
- states[0].GetOrNewStateObject(addr)
+ states[0].getOrNewStateObject(addr)
states[0].SetState(addr, key, val1)
states[0].SetBalance(addr, balance1)
states[0].FlushMVWriteSet()
@@ -877,11 +878,11 @@ func TestMVHashMapWriteNoConflict(t *testing.T) {
key1 := common.HexToHash("0x01")
key2 := common.HexToHash("0x02")
val1 := common.HexToHash("0x01")
- balance1 := new(big.Int).SetUint64(uint64(100))
+ balance1 := uint256.NewInt(100)
val2 := common.HexToHash("0x02")
// Tx0 write
- states[0].GetOrNewStateObject(addr)
+ states[0].getOrNewStateObject(addr)
states[0].FlushMVWriteSet()
// Tx2 write
@@ -969,25 +970,25 @@ func TestApplyMVWriteSet(t *testing.T) {
key1 := common.HexToHash("0x01")
key2 := common.HexToHash("0x02")
val1 := common.HexToHash("0x01")
- balance1 := new(big.Int).SetUint64(uint64(100))
+ balance1 := uint256.NewInt(100)
val2 := common.HexToHash("0x02")
- balance2 := new(big.Int).SetUint64(uint64(200))
+ balance2 := uint256.NewInt(200)
code := []byte{1, 2, 3}
// Tx0 write
- states[0].GetOrNewStateObject(addr1)
+ states[0].getOrNewStateObject(addr1)
states[0].SetState(addr1, key1, val1)
states[0].SetBalance(addr1, balance1)
states[0].SetState(addr2, key2, val2)
- states[0].GetOrNewStateObject(addr3)
+ states[0].getOrNewStateObject(addr3)
states[0].Finalise(true)
states[0].FlushMVWriteSet()
- sSingleProcess.GetOrNewStateObject(addr1)
+ sSingleProcess.getOrNewStateObject(addr1)
sSingleProcess.SetState(addr1, key1, val1)
sSingleProcess.SetBalance(addr1, balance1)
sSingleProcess.SetState(addr2, key2, val2)
- sSingleProcess.GetOrNewStateObject(addr3)
+ sSingleProcess.getOrNewStateObject(addr3)
sClean.ApplyMVWriteSet(states[0].MVWriteList())
@@ -1042,7 +1043,7 @@ func TestApplyMVWriteSet(t *testing.T) {
func TestCopyOfCopy(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
addr := common.HexToAddress("aaaa")
- state.SetBalance(addr, big.NewInt(42))
+ state.SetBalance(addr, uint256.NewInt(42))
if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
t.Fatalf("1st copy fail, expected 42, got %v", got)
@@ -1066,11 +1067,11 @@ func TestCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
@@ -1087,7 +1088,7 @@ func TestCopyCommitCopy(t *testing.T) {
}
// Copy the non-committed state database and check pre/post commit balance
copyOne := state.Copy()
- if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
@@ -1104,7 +1105,7 @@ func TestCopyCommitCopy(t *testing.T) {
}
// Copy the copy and check the balance once more
copyTwo := copyOne.Copy()
- if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
}
@@ -1121,7 +1122,7 @@ func TestCopyCommitCopy(t *testing.T) {
// Commit state, ensure states can be loaded from disk
root, _ := state.Commit(0, false)
state, _ = New(root, tdb, nil)
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -1147,11 +1148,11 @@ func TestCopyCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
@@ -1168,7 +1169,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the non-committed state database and check pre/post commit balance
copyOne := state.Copy()
- if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
}
@@ -1185,7 +1186,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the copy and check the balance once more
copyTwo := copyOne.Copy()
- if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
@@ -1202,7 +1203,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the copy-copy and check the balance once more
copyThree := copyTwo.Copy()
- if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyThree.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
}
@@ -1227,11 +1228,11 @@ func TestCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -1246,7 +1247,7 @@ func TestCommitCopy(t *testing.T) {
// Copy the committed state database, the copied one is not functional.
state.Commit(0, true)
copied := state.Copy()
- if balance := copied.GetBalance(addr); balance.Cmp(big.NewInt(0)) != 0 {
+ if balance := copied.GetBalance(addr); balance.Cmp(uint256.NewInt(0)) != 0 {
t.Fatalf("unexpected balance: have %v", balance)
}
if code := copied.GetCode(addr); code != nil {
@@ -1276,7 +1277,7 @@ func TestDeleteCreateRevert(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
addr := common.BytesToAddress([]byte("so"))
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
root, _ := state.Commit(0, false)
state, _ = New(root, state.db, state.snaps)
@@ -1286,7 +1287,7 @@ func TestDeleteCreateRevert(t *testing.T) {
state.Finalise(true)
id := state.Snapshot()
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
state.RevertToSnapshot(id)
// Commit the entire state and make sure we don't crash and have the correct state
@@ -1309,35 +1310,35 @@ func TestMissingTrieNodes(t *testing.T) {
func testMissingTrieNodes(t *testing.T, scheme string) {
// Create an initial state with a few accounts
var (
- triedb *trie.Database
- memDb = rawdb.NewMemoryDatabase()
+ tdb *triedb.Database
+ memDb = rawdb.NewMemoryDatabase()
)
if scheme == rawdb.PathScheme {
- triedb = trie.NewDatabase(memDb, &trie.Config{PathDB: &pathdb.Config{
+ tdb = triedb.NewDatabase(memDb, &triedb.Config{PathDB: &pathdb.Config{
CleanCacheSize: 0,
DirtyCacheSize: 0,
}}) // disable caching
} else {
- triedb = trie.NewDatabase(memDb, &trie.Config{HashDB: &hashdb.Config{
+ tdb = triedb.NewDatabase(memDb, &triedb.Config{HashDB: &hashdb.Config{
CleanCacheSize: 0,
}}) // disable caching
}
- db := NewDatabaseWithNodeDB(memDb, triedb)
+ db := NewDatabaseWithNodeDB(memDb, tdb)
var root common.Hash
state, _ := New(types.EmptyRootHash, db, nil)
addr := common.BytesToAddress([]byte("so"))
{
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.SetCode(addr, []byte{1, 2, 3})
a2 := common.BytesToAddress([]byte("another"))
- state.SetBalance(a2, big.NewInt(100))
+ state.SetBalance(a2, uint256.NewInt(100))
state.SetCode(a2, []byte{1, 2, 4})
root, _ = state.Commit(0, false)
t.Logf("root: %x", root)
// force-flush
- triedb.Commit(root, false)
+ tdb.Commit(root, false)
}
// Create a new state on the old root
state, _ = New(root, db, nil)
@@ -1358,7 +1359,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
t.Errorf("expected %d, got %d", exp, got)
}
// Modify the state
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
root, err := state.Commit(0, false)
if err == nil {
t.Fatalf("expected error, got root :%x", root)
@@ -1575,7 +1576,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
// Create a state trie with many accounts and slots
var (
memdb = rawdb.NewMemoryDatabase()
- triedb = trie.NewDatabase(memdb, nil)
+ triedb = triedb.NewDatabase(memdb, nil)
statedb = NewDatabaseWithNodeDB(memdb, triedb)
state, _ = New(types.EmptyRootHash, statedb, nil)
)
@@ -1655,7 +1656,7 @@ func TestStateDBTransientStorage(t *testing.T) {
func TestResetObject(t *testing.T) {
var (
disk = rawdb.NewMemoryDatabase()
- tdb = trie.NewDatabase(disk, nil)
+ tdb = triedb.NewDatabase(disk, nil)
db = NewDatabaseWithNodeDB(disk, tdb)
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
state, _ = New(types.EmptyRootHash, db, snaps)
@@ -1664,13 +1665,13 @@ func TestResetObject(t *testing.T) {
slotB = common.HexToHash("0x2")
)
// Initialize account with balance and storage in first transaction.
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.SetState(addr, slotA, common.BytesToHash([]byte{0x1}))
state.IntermediateRoot(true)
// Reset account and mutate balance and storages
state.CreateAccount(addr)
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
state.SetState(addr, slotB, common.BytesToHash([]byte{0x2}))
root, _ := state.Commit(0, true)
@@ -1689,14 +1690,14 @@ func TestResetObject(t *testing.T) {
func TestDeleteStorage(t *testing.T) {
var (
disk = rawdb.NewMemoryDatabase()
- tdb = trie.NewDatabase(disk, nil)
+ tdb = triedb.NewDatabase(disk, nil)
db = NewDatabaseWithNodeDB(disk, tdb)
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
state, _ = New(types.EmptyRootHash, db, snaps)
addr = common.HexToAddress("0x1")
)
// Initialize account and populate storage
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.CreateAccount(addr)
for i := 0; i < 1000; i++ {
slot := common.Hash(uint256.NewInt(uint64(i)).Bytes32())
@@ -1708,7 +1709,7 @@ func TestDeleteStorage(t *testing.T) {
fastState, _ := New(root, db, snaps)
slowState, _ := New(root, db, nil)
- obj := fastState.GetOrNewStateObject(addr)
+ obj := fastState.getOrNewStateObject(addr)
storageRoot := obj.data.Root
_, _, fastNodes, err := fastState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot)
diff --git a/core/state/sync.go b/core/state/sync.go
index 44f4e08463..4091274f27 100644
--- a/core/state/sync.go
+++ b/core/state/sync.go
@@ -24,7 +24,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
)
-// NewStateSync create a new state trie download scheduler.
+// NewStateSync creates a new state trie download scheduler.
func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync {
// Register the storage slot callback if the external callback is specified.
var onSlot func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index ef07b2414e..33a7f94a43 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -18,7 +18,6 @@ package state
import (
"bytes"
- "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -28,29 +27,31 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
)
// testAccount is the data associated with an account used by the state tests.
type testAccount struct {
address common.Address
- balance *big.Int
+ balance *uint256.Int
nonce uint64
code []byte
}
// makeTestState create a sample test state to test node-wise reconstruction.
-func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, common.Hash, []*testAccount) {
+func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, common.Hash, []*testAccount) {
// Create an empty state
- config := &trie.Config{Preimages: true}
+ config := &triedb.Config{Preimages: true}
if scheme == rawdb.PathScheme {
config.PathDB = pathdb.Defaults
} else {
config.HashDB = hashdb.Defaults
}
db := rawdb.NewMemoryDatabase()
- nodeDb := trie.NewDatabase(db, config)
+ nodeDb := triedb.NewDatabase(db, config)
sdb := NewDatabaseWithNodeDB(db, nodeDb)
state, _ := New(types.EmptyRootHash, sdb, nil)
@@ -58,11 +59,11 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
var accounts []*testAccount
for i := byte(0); i < 96; i++ {
- obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i}))
acc := &testAccount{address: common.BytesToAddress([]byte{i})}
- obj.AddBalance(big.NewInt(int64(11 * i)))
- acc.balance = big.NewInt(int64(11 * i))
+ obj.AddBalance(uint256.NewInt(uint64(11 * i)))
+ acc.balance = uint256.NewInt(uint64(11 * i))
obj.SetNonce(uint64(42 * i))
acc.nonce = uint64(42 * i)
@@ -89,7 +90,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
// checkStateAccounts cross references a reconstructed state with an expected
// account array.
func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root common.Hash, accounts []*testAccount) {
- var config trie.Config
+ var config triedb.Config
if scheme == rawdb.PathScheme {
config.PathDB = pathdb.Defaults
}
@@ -119,7 +120,7 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root com
// checkStateConsistency checks that all data of a state root is present.
func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) error {
- config := &trie.Config{Preimages: true}
+ config := &triedb.Config{Preimages: true}
if scheme == rawdb.PathScheme {
config.PathDB = pathdb.Defaults
}
@@ -136,8 +137,8 @@ func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) e
// Tests that an empty state is not scheduled for syncing.
func TestEmptyStateSync(t *testing.T) {
- dbA := trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)
- dbB := trie.NewDatabase(rawdb.NewMemoryDatabase(), &trie.Config{PathDB: pathdb.Defaults})
+ dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &triedb.Config{PathDB: pathdb.Defaults})
sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme())
if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
diff --git a/core/state/trie_prefetcher_test.go b/core/state/trie_prefetcher_test.go
index 1501931e23..acc1f94092 100644
--- a/core/state/trie_prefetcher_test.go
+++ b/core/state/trie_prefetcher_test.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
)
func filledStateDB() *StateDB {
@@ -34,9 +35,9 @@ func filledStateDB() *StateDB {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
for i := 0; i < 100; i++ {
sk := common.BigToHash(big.NewInt(int64(i)))
diff --git a/core/state_processor.go b/core/state_processor.go
index ba04f62e98..2dac769948 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -148,11 +149,11 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
statedb.SetMVHashmap(nil)
if evm.ChainConfig().IsLondon(blockNumber) {
- statedb.AddBalance(result.BurntContractAddress, result.FeeBurnt)
+ statedb.AddBalance(result.BurntContractAddress, uint256.NewInt(result.FeeBurnt.Uint64()))
}
// TODO(raneet10) Double check
- statedb.AddBalance(evm.Context.Coinbase, result.FeeTipped)
+ statedb.AddBalance(evm.Context.Coinbase, uint256.NewInt(result.FeeTipped.Uint64()))
output1 := new(big.Int).SetBytes(result.SenderInitBalance.Bytes())
output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes())
@@ -166,7 +167,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
result.FeeTipped,
result.SenderInitBalance,
- coinbaseBalance,
+ coinbaseBalance.ToBig(),
output1.Sub(output1, result.FeeTipped),
output2.Add(output2, result.FeeTipped),
)
@@ -250,6 +251,6 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *stat
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress)
- _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.Big0, nil)
+ _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560, nil)
statedb.Finalise(true)
}
diff --git a/core/state_processor_test.go b/core/state_processor_test.go
index 21a2143613..a84151741c 100644
--- a/core/state_processor_test.go
+++ b/core/state_processor_test.go
@@ -119,12 +119,12 @@ func TestStateProcessorErrors(t *testing.T) {
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: config,
- Alloc: GenesisAlloc{
- common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
+ Alloc: types.GenesisAlloc{
+ common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: 0,
},
- common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{
+ common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): types.Account{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: math.MaxUint64,
},
@@ -234,7 +234,7 @@ func TestStateProcessorErrors(t *testing.T) {
txs: []*types.Transaction{
mkDynamicTx(0, common.Address{}, params.TxGas, bigNumber, bigNumber),
},
- want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000",
+ want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 required balance exceeds 256 bits",
},
{ // ErrMaxInitCodeSizeExceeded
txs: []*types.Transaction{
@@ -283,8 +283,8 @@ func TestStateProcessorErrors(t *testing.T) {
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
},
- Alloc: GenesisAlloc{
- common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
+ Alloc: types.GenesisAlloc{
+ common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: 0,
},
@@ -321,8 +321,8 @@ func TestStateProcessorErrors(t *testing.T) {
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: config,
- Alloc: GenesisAlloc{
- common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
+ Alloc: types.GenesisAlloc{
+ common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: 0,
Code: common.FromHex("0xB0B0FACE"),
diff --git a/core/state_transition.go b/core/state_transition.go
index 3d6739d896..57a4426fe5 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -18,7 +18,6 @@ package core
import (
"context"
- "errors"
"fmt"
"math"
"math/big"
@@ -27,7 +26,9 @@ import (
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// ExecutionResult includes all output after executing given evm
@@ -73,7 +74,7 @@ func (result *ExecutionResult) Revert() []byte {
}
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
-func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028 bool, isEIP3860 bool) (uint64, error) {
+func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028, isEIP3860 bool) (uint64, error) {
// Set the starting gas for the raw transaction
var gas uint64
if isContractCreation && isHomestead {
@@ -283,7 +284,11 @@ func (st *StateTransition) buyGas() error {
mgval.Add(mgval, blobFee)
}
}
- if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
+ balanceCheckU256, overflow := uint256.FromBig(balanceCheck)
+ if overflow {
+ return fmt.Errorf("%w: address %v required balance exceeds 256 bits", ErrInsufficientFunds, st.msg.From.Hex())
+ }
+ if have, want := st.state.GetBalance(st.msg.From), balanceCheckU256; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
@@ -294,7 +299,8 @@ func (st *StateTransition) buyGas() error {
st.gasRemaining += st.msg.GasLimit
st.initialGas = st.msg.GasLimit
- st.state.SubBalance(st.msg.From, mgval)
+ mgvalU256, _ := uint256.FromBig(mgval)
+ st.state.SubBalance(st.msg.From, mgvalU256)
return nil
}
@@ -351,13 +357,18 @@ func (st *StateTransition) preCheck() error {
}
// Check the blob version validity
if msg.BlobHashes != nil {
+ // The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally
+ // has it as a non-nillable value, so any msg derived from blob transaction has it non-nil.
+ // However, messages created through RPC (eth_call) don't have this restriction.
+ if msg.To == nil {
+ return ErrBlobTxCreate
+ }
if len(msg.BlobHashes) == 0 {
- return errors.New("blob transaction missing blob hashes")
+ return ErrMissingBlobHashes
}
for i, hash := range msg.BlobHashes {
- if hash[0] != params.BlobTxHashVersion {
- return fmt.Errorf("blob %d hash version mismatch (have %d, supported %d)",
- i, hash[0], params.BlobTxHashVersion)
+ if !kzg4844.IsValidVersionedHash(hash[:]) {
+ return fmt.Errorf("blob %d has invalid hash version", i)
}
}
}
@@ -392,7 +403,7 @@ func (st *StateTransition) preCheck() error {
func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*ExecutionResult, error) {
input1 := st.state.GetBalance(st.msg.From)
- var input2 *big.Int
+ var input2 *uint256.Int
if !st.noFeeBurnAndTip {
input2 = st.state.GetBalance(st.evm.Context.Coinbase)
@@ -440,7 +451,11 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
st.gasRemaining -= gas
// Check clause 6
- if msg.Value.Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From, msg.Value) {
+ value, overflow := uint256.FromBig(msg.Value)
+ if overflow {
+ return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex())
+ }
+ if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From, value) {
return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex())
}
@@ -460,12 +475,15 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
)
if contractCreation {
+
// nolint : contextcheck
- ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, msg.Value)
- } else {
+ ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value)
+
// Increment the nonce for the next transaction
+ } else {
st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1)
- ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value, interruptCtx)
+
+ ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value, interruptCtx)
}
var gasRefund uint64
@@ -477,10 +495,10 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
gasRefund = st.refundGas(params.RefundQuotientEIP3529)
}
- effectiveTip := msg.GasPrice
+ effectiveTip := uint256.NewInt(msg.GasPrice.Uint64())
if rules.IsLondon {
- effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
+ effectiveTip = cmath.BigMinUint256(cmath.BigIntToUint256Int(msg.GasTipCap), new(uint256.Int).Sub(cmath.BigIntToUint256Int(msg.GasFeeCap), cmath.BigIntToUint256Int(st.evm.Context.BaseFee)))
}
// TODO(raneet10): Double check. We might want to inculcate this fix in a separate condition
@@ -494,15 +512,15 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
// st.state.AddBalance(st.evm.Context.Coinbase, fee)
// }
- amount := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)
+ amount := new(uint256.Int).Mul(new(uint256.Int).SetUint64(st.gasUsed()), effectiveTip)
- var burnAmount *big.Int
+ var burnAmount *uint256.Int
var burntContractAddress common.Address
if rules.IsLondon {
burntContractAddress = common.HexToAddress(st.evm.ChainConfig().Bor.CalculateBurntContract(st.evm.Context.BlockNumber.Uint64()))
- burnAmount = new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee)
+ burnAmount = new(uint256.Int).Mul(new(uint256.Int).SetUint64(st.gasUsed()), cmath.BigIntToUint256Int(st.evm.Context.BaseFee))
if !st.noFeeBurnAndTip {
st.state.AddBalance(burntContractAddress, burnAmount)
@@ -523,11 +541,11 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
msg.From,
st.evm.Context.Coinbase,
- amount,
- input1,
- input2,
- output1.Sub(output1, amount),
- output2.Add(output2, amount),
+ amount.ToBig(),
+ input1.ToBig(),
+ input2.ToBig(),
+ output1.Sub(output1, amount.ToBig()),
+ output2.Add(output2, amount.ToBig()),
)
}
@@ -536,10 +554,10 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
RefundedGas: gasRefund,
Err: vmerr,
ReturnData: ret,
- SenderInitBalance: input1,
- FeeBurnt: burnAmount,
+ SenderInitBalance: input1.ToBig(),
+ FeeBurnt: burnAmount.ToBig(),
BurntContractAddress: burntContractAddress,
- FeeTipped: amount,
+ FeeTipped: amount.ToBig(),
}, nil
}
@@ -553,7 +571,8 @@ func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
st.gasRemaining += refund
// Return ETH for remaining gas, exchanged at the original rate.
- remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice)
+ remaining := uint256.NewInt(st.gasRemaining)
+ remaining = remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice))
st.state.AddBalance(st.msg.From, remaining)
// Also return remaining gas to the block gas counter so it is
diff --git a/core/txindexer.go b/core/txindexer.go
new file mode 100644
index 0000000000..70fe5f3322
--- /dev/null
+++ b/core/txindexer.go
@@ -0,0 +1,219 @@
+// Copyright 2024 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 core
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// TxIndexProgress is the struct describing the progress for transaction indexing.
+type TxIndexProgress struct {
+ Indexed uint64 // number of blocks whose transactions are indexed
+ Remaining uint64 // number of blocks whose transactions are not indexed yet
+}
+
+// Done returns an indicator if the transaction indexing is finished.
+func (progress TxIndexProgress) Done() bool {
+ return progress.Remaining == 0
+}
+
+// txIndexer is the module responsible for maintaining transaction indexes
+// according to the configured indexing range by users.
+type txIndexer struct {
+ // limit is the maximum number of blocks from head whose tx indexes
+ // are reserved:
+ // * 0: means the entire chain should be indexed
+ // * N: means the latest N blocks [HEAD-N+1, HEAD] should be indexed
+ // and all others shouldn't.
+ limit uint64
+ db ethdb.Database
+ progress chan chan TxIndexProgress
+ term chan chan struct{}
+ closed chan struct{}
+}
+
+// newTxIndexer initializes the transaction indexer.
+func newTxIndexer(limit uint64, chain *BlockChain) *txIndexer {
+ indexer := &txIndexer{
+ limit: limit,
+ db: chain.db,
+ progress: make(chan chan TxIndexProgress),
+ term: make(chan chan struct{}),
+ closed: make(chan struct{}),
+ }
+ go indexer.loop(chain)
+
+ var msg string
+ if limit == 0 {
+ msg = "entire chain"
+ } else {
+ msg = fmt.Sprintf("last %d blocks", limit)
+ }
+ log.Info("Initialized transaction indexer", "range", msg)
+
+ return indexer
+}
+
+// run executes the scheduled indexing/unindexing task in a separate thread.
+// If the stop channel is closed, the task should be terminated as soon as
+// possible, the done channel will be closed once the task is finished.
+func (indexer *txIndexer) run(tail *uint64, head uint64, stop chan struct{}, done chan struct{}) {
+ defer func() { close(done) }()
+
+ // Short circuit if chain is empty and nothing to index.
+ if head == 0 {
+ return
+ }
+ // The tail flag is not existent, it means the node is just initialized
+ // and all blocks in the chain (part of them may from ancient store) are
+ // not indexed yet, index the chain according to the configured limit.
+ if tail == nil {
+ from := uint64(0)
+ if indexer.limit != 0 && head >= indexer.limit {
+ from = head - indexer.limit + 1
+ }
+ rawdb.IndexTransactions(indexer.db, from, head+1, stop, true)
+ return
+ }
+ // The tail flag is existent (which means indexes in [tail, head] should be
+ // present), while the whole chain are requested for indexing.
+ if indexer.limit == 0 || head < indexer.limit {
+ if *tail > 0 {
+ // It can happen when chain is rewound to a historical point which
+ // is even lower than the indexes tail, recap the indexing target
+ // to new head to avoid reading non-existent block bodies.
+ end := *tail
+ if end > head+1 {
+ end = head + 1
+ }
+ rawdb.IndexTransactions(indexer.db, 0, end, stop, true)
+ }
+ return
+ }
+ // The tail flag is existent, adjust the index range according to configured
+ // limit and the latest chain head.
+ if head-indexer.limit+1 < *tail {
+ // Reindex a part of missing indices and rewind index tail to HEAD-limit
+ rawdb.IndexTransactions(indexer.db, head-indexer.limit+1, *tail, stop, true)
+ } else {
+ // Unindex a part of stale indices and forward index tail to HEAD-limit
+ rawdb.UnindexTransactions(indexer.db, *tail, head-indexer.limit+1, stop, false)
+ }
+}
+
+// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending
+// on the received chain event.
+func (indexer *txIndexer) loop(chain *BlockChain) {
+ defer close(indexer.closed)
+
+ // Listening to chain events and manipulate the transaction indexes.
+ var (
+ stop chan struct{} // Non-nil if background routine is active.
+ done chan struct{} // Non-nil if background routine is active.
+ lastHead uint64 // The latest announced chain head (whose tx indexes are assumed created)
+ lastTail = rawdb.ReadTxIndexTail(indexer.db) // The oldest indexed block, nil means nothing indexed
+
+ headCh = make(chan ChainHeadEvent)
+ sub = chain.SubscribeChainHeadEvent(headCh)
+ )
+ defer sub.Unsubscribe()
+
+ // Launch the initial processing if chain is not empty (head != genesis).
+ // This step is useful in these scenarios that chain has no progress.
+ if head := rawdb.ReadHeadBlock(indexer.db); head != nil && head.Number().Uint64() != 0 {
+ stop = make(chan struct{})
+ done = make(chan struct{})
+ lastHead = head.Number().Uint64()
+ go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.NumberU64(), stop, done)
+ }
+ for {
+ select {
+ case head := <-headCh:
+ if done == nil {
+ stop = make(chan struct{})
+ done = make(chan struct{})
+ go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.Block.NumberU64(), stop, done)
+ }
+ lastHead = head.Block.NumberU64()
+ case <-done:
+ stop = nil
+ done = nil
+ lastTail = rawdb.ReadTxIndexTail(indexer.db)
+ case ch := <-indexer.progress:
+ ch <- indexer.report(lastHead, lastTail)
+ case ch := <-indexer.term:
+ if stop != nil {
+ close(stop)
+ }
+ if done != nil {
+ log.Info("Waiting background transaction indexer to exit")
+ <-done
+ }
+ close(ch)
+ return
+ }
+ }
+}
+
+// report returns the tx indexing progress.
+func (indexer *txIndexer) report(head uint64, tail *uint64) TxIndexProgress {
+ total := indexer.limit
+ if indexer.limit == 0 || total > head {
+ total = head + 1 // genesis included
+ }
+ var indexed uint64
+ if tail != nil {
+ indexed = head - *tail + 1
+ }
+ // The value of indexed might be larger than total if some blocks need
+ // to be unindexed, avoiding a negative remaining.
+ var remaining uint64
+ if indexed < total {
+ remaining = total - indexed
+ }
+ return TxIndexProgress{
+ Indexed: indexed,
+ Remaining: remaining,
+ }
+}
+
+// txIndexProgress retrieves the tx indexing progress, or an error if the
+// background tx indexer is already stopped.
+func (indexer *txIndexer) txIndexProgress() (TxIndexProgress, error) {
+ ch := make(chan TxIndexProgress, 1)
+ select {
+ case indexer.progress <- ch:
+ return <-ch, nil
+ case <-indexer.closed:
+ return TxIndexProgress{}, errors.New("indexer is closed")
+ }
+}
+
+// close shutdown the indexer. Safe to be called for multiple times.
+func (indexer *txIndexer) close() {
+ ch := make(chan struct{})
+ select {
+ case indexer.term <- ch:
+ <-ch
+ case <-indexer.closed:
+ }
+}
diff --git a/core/txindexer_test.go b/core/txindexer_test.go
new file mode 100644
index 0000000000..636fc095cc
--- /dev/null
+++ b/core/txindexer_test.go
@@ -0,0 +1,243 @@
+// Copyright 2024 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 core
+
+import (
+ "math/big"
+ "os"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// TestTxIndexer tests the functionalities for managing transaction indexes.
+func TestTxIndexer(t *testing.T) {
+ var (
+ testBankKey, _ = crypto.GenerateKey()
+ testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
+ testBankFunds = big.NewInt(1000000000000000000)
+
+ gspec = &Genesis{
+ Config: params.TestChainConfig,
+ Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ }
+ engine = ethash.NewFaker()
+ nonce = uint64(0)
+ chainHead = uint64(128)
+ )
+ _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, int(chainHead), func(i int, gen *BlockGen) {
+ tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey)
+ gen.AddTx(tx)
+ nonce += 1
+ })
+
+ // verifyIndexes checks if the transaction indexes are present or not
+ // of the specified block.
+ verifyIndexes := func(db ethdb.Database, number uint64, exist bool) {
+ if number == 0 {
+ return
+ }
+ block := blocks[number-1]
+ for _, tx := range block.Transactions() {
+ lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
+ if exist && lookup == nil {
+ t.Fatalf("missing %d %x", number, tx.Hash().Hex())
+ }
+ if !exist && lookup != nil {
+ t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
+ }
+ }
+ }
+ verify := func(db ethdb.Database, expTail uint64, indexer *txIndexer) {
+ tail := rawdb.ReadTxIndexTail(db)
+ if tail == nil {
+ t.Fatal("Failed to write tx index tail")
+ }
+ if *tail != expTail {
+ t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
+ }
+ if *tail != 0 {
+ for number := uint64(0); number < *tail; number += 1 {
+ verifyIndexes(db, number, false)
+ }
+ }
+ for number := *tail; number <= chainHead; number += 1 {
+ verifyIndexes(db, number, true)
+ }
+ progress := indexer.report(chainHead, tail)
+ if !progress.Done() {
+ t.Fatalf("Expect fully indexed")
+ }
+ }
+
+ var cases = []struct {
+ limitA uint64
+ tailA uint64
+ limitB uint64
+ tailB uint64
+ limitC uint64
+ tailC uint64
+ }{
+ {
+ // LimitA: 0
+ // TailA: 0
+ //
+ // all blocks are indexed
+ limitA: 0,
+ tailA: 0,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 64
+ // TailA: 65
+ //
+ // block [65, 128] are indexed
+ limitA: 64,
+ tailA: 65,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 127
+ // TailA: 2
+ //
+ // block [2, 128] are indexed
+ limitA: 127,
+ tailA: 2,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 128
+ // TailA: 1
+ //
+ // block [2, 128] are indexed
+ limitA: 128,
+ tailA: 1,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 129
+ // TailA: 0
+ //
+ // block [0, 128] are indexed
+ limitA: 129,
+ tailA: 0,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ }
+ for _, c := range cases {
+ frdir := t.TempDir()
+ db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
+ rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), nil, big.NewInt(0))
+
+ // Index the initial blocks from ancient store
+ indexer := &txIndexer{
+ limit: c.limitA,
+ db: db,
+ progress: make(chan chan TxIndexProgress),
+ }
+ indexer.run(nil, 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailA, indexer)
+
+ indexer.limit = c.limitB
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailB, indexer)
+
+ indexer.limit = c.limitC
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailC, indexer)
+
+ // Recover all indexes
+ indexer.limit = 0
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, 0, indexer)
+
+ db.Close()
+ os.RemoveAll(frdir)
+ }
+}
diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go
index 431bfd9121..afe4f8191c 100644
--- a/core/txpool/blobpool/blobpool.go
+++ b/core/txpool/blobpool/blobpool.go
@@ -268,7 +268,7 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
// going up, crossing the smaller positive jump counter). As such, the pool
// cares only about the min of the two delta values for eviction priority.
//
-// priority = min(delta-basefee, delta-blobfee)
+// priority = min(deltaBasefee, deltaBlobfee)
//
// - The above very aggressive dimensionality and noise reduction should result
// in transaction being grouped into a small number of buckets, the further
@@ -280,7 +280,7 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
// with high fee caps since it could enable pool wars. As such, any positive
// priority will be grouped together.
//
-// priority = min(delta-basefee, delta-blobfee, 0)
+// priority = min(deltaBasefee, deltaBlobfee, 0)
//
// Optimisation tradeoffs:
//
@@ -342,7 +342,7 @@ func (p *BlobPool) Filter(tx *types.Transaction) bool {
// Init sets the gas price needed to keep a transaction in the pool and the chain
// head to allow balance / nonce checks. The transaction journal will be loaded
// from disk and filtered based on the provided starting settings.
-func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.AddressReserver) error {
+func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error {
p.reserve = reserve
var (
@@ -360,7 +360,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
}
}
// Initialize the state with head block, or fallback to empty one in
- // case the head state is not available(might occur when node is not
+ // case the head state is not available (might occur when node is not
// fully synced).
state, err := p.chain.StateAt(head.Root)
if err != nil {
@@ -371,14 +371,14 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
}
p.head, p.state = head, state
- // Index all transactions on disk and delete anything inprocessable
+ // Index all transactions on disk and delete anything unprocessable
var fails []uint64
index := func(id uint64, size uint32, blob []byte) {
if p.parseTransaction(id, size, blob) != nil {
fails = append(fails, id)
}
}
- store, err := billy.Open(billy.Options{Path: queuedir}, newSlotter(), index)
+ store, err := billy.Open(billy.Options{Path: queuedir, Repair: true}, newSlotter(), index)
if err != nil {
return err
}
@@ -386,6 +386,8 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
if len(fails) > 0 {
log.Warn("Dropping invalidated blob transactions", "ids", fails)
+ dropInvalidMeter.Mark(int64(len(fails)))
+
for _, id := range fails {
if err := p.store.Delete(id); err != nil {
p.Close()
@@ -400,7 +402,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
}
var (
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head))
- blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice))
+ blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
)
if p.head.ExcessBlobGas != nil {
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*p.head.ExcessBlobGas))
@@ -418,7 +420,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
basefeeGauge.Update(int64(basefee.Uint64()))
blobfeeGauge.Update(int64(blobfee.Uint64()))
- p.SetGasTip(gasTip)
+ p.SetGasTip(new(big.Int).SetUint64(gasTip))
// Since the user might have modified their pool's capacity, evict anything
// above the current allowance
@@ -434,8 +436,10 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
// Close closes down the underlying persistent store.
func (p *BlobPool) Close() error {
var errs []error
- if err := p.limbo.Close(); err != nil {
- errs = append(errs, err)
+ if p.limbo != nil { // Close might be invoked due to error in constructor, before p,limbo is set
+ if err := p.limbo.Close(); err != nil {
+ errs = append(errs, err)
+ }
}
if err := p.store.Close(); err != nil {
errs = append(errs, err)
@@ -467,7 +471,13 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
}
meta := newBlobTxMeta(id, size, tx)
-
+ if _, exists := p.lookup[meta.hash]; exists {
+ // This path is only possible after a crash, where deleted items are not
+ // removed via the normal shutdown-startup procedure and thus may get
+ // partially resurrected.
+ log.Error("Rejecting duplicate blob pool entry", "id", id, "hash", tx.Hash())
+ return errors.New("duplicate blob entry")
+ }
sender, err := p.signer.Sender(tx)
if err != nil {
// This path is impossible unless the signature validity changes across
@@ -530,15 +540,17 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
}
delete(p.index, addr)
delete(p.spent, addr)
- if inclusions != nil { // only during reorgs will the heap will be initialized
+ if inclusions != nil { // only during reorgs will the heap be initialized
heap.Remove(p.evict, p.evict.index[addr])
}
p.reserve(addr, false)
if gapped {
log.Warn("Dropping dangling blob transactions", "from", addr, "missing", next, "drop", nonces, "ids", ids)
+ dropDanglingMeter.Mark(int64(len(ids)))
} else {
log.Trace("Dropping filled blob transactions", "from", addr, "filled", nonces, "ids", ids)
+ dropFilledMeter.Mark(int64(len(ids)))
}
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
@@ -569,6 +581,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
txs = txs[1:]
}
log.Trace("Dropping overlapped blob transactions", "from", addr, "overlapped", nonces, "ids", ids, "left", len(txs))
+ dropOverlappedMeter.Mark(int64(len(ids)))
+
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err)
@@ -583,7 +597,7 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
for i := 1; i < len(txs); i++ {
- // If there's no nonce gap, initialize the evicion thresholds as the
+ // If there's no nonce gap, initialize the eviction thresholds as the
// minimum between the cumulative thresholds and the current tx fees
if txs[i].nonce == txs[i-1].nonce+1 {
txs[i].evictionExecTip = txs[i-1].evictionExecTip
@@ -600,10 +614,30 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
}
continue
}
- // Sanity check that there's no double nonce. This case would be a coding
- // error, but better know about it
+ // Sanity check that there's no double nonce. This case would generally
+ // be a coding error, so better know about it.
+ //
+ // Also, Billy behind the blobpool does not journal deletes. A process
+ // crash would result in previously deleted entities being resurrected.
+ // That could potentially cause a duplicate nonce to appear.
if txs[i].nonce == txs[i-1].nonce {
- log.Error("Duplicate nonce blob transaction", "from", addr, "nonce", txs[i].nonce)
+ id := p.lookup[txs[i].hash]
+
+ log.Error("Dropping repeat nonce blob transaction", "from", addr, "nonce", txs[i].nonce, "id", id)
+ dropRepeatedMeter.Mark(1)
+
+ p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].costCap)
+ p.stored -= uint64(txs[i].size)
+ delete(p.lookup, txs[i].hash)
+
+ if err := p.store.Delete(id); err != nil {
+ log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err)
+ }
+ txs = append(txs[:i], txs[i+1:]...)
+ p.index[addr] = txs
+
+ i--
+ continue
}
// Otherwise if there's a nonce gap evict all later transactions
var (
@@ -621,6 +655,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
txs = txs[:i]
log.Error("Dropping gapped blob transactions", "from", addr, "missing", txs[i-1].nonce+1, "drop", nonces, "ids", ids)
+ dropGappedMeter.Mark(int64(len(ids)))
+
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err)
@@ -632,7 +668,7 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
// Ensure that there's no over-draft, this is expected to happen when some
// transactions get included without publishing on the network
var (
- balance = uint256.MustFromBig(p.state.GetBalance(addr))
+ balance = p.state.GetBalance(addr)
spent = p.spent[addr]
)
if spent.Cmp(balance) > 0 {
@@ -657,7 +693,7 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
if len(txs) == 0 {
delete(p.index, addr)
delete(p.spent, addr)
- if inclusions != nil { // only during reorgs will the heap will be initialized
+ if inclusions != nil { // only during reorgs will the heap be initialized
heap.Remove(p.evict, p.evict.index[addr])
}
p.reserve(addr, false)
@@ -665,6 +701,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
p.index[addr] = txs
}
log.Warn("Dropping overdrafted blob transactions", "from", addr, "balance", balance, "spent", spent, "drop", nonces, "ids", ids)
+ dropOverdraftedMeter.Mark(int64(len(ids)))
+
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err)
@@ -695,6 +733,8 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
p.index[addr] = txs
log.Warn("Dropping overcapped blob transactions", "from", addr, "kept", len(txs), "drop", nonces, "ids", ids)
+ dropOvercappedMeter.Mark(int64(len(ids)))
+
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err)
@@ -769,7 +809,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
}
}
// Recheck the account's pooled transactions to drop included and
- // invalidated one
+ // invalidated ones
p.recheck(addr, inclusions)
}
if len(adds) > 0 {
@@ -952,7 +992,7 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
return err
}
- // Update the indixes and metrics
+ // Update the indices and metrics
meta := newBlobTxMeta(id, p.store.Size(id), tx)
if _, ok := p.index[addr]; !ok {
if err := p.reserve(addr, true); err != nil {
@@ -1019,6 +1059,8 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
}
// Clear out the transactions from the data store
log.Warn("Dropping underpriced blob transaction", "from", addr, "rejected", tx.nonce, "tip", tx.execTipCap, "want", tip, "drop", nonces, "ids", ids)
+ dropUnderpricedMeter.Mark(int64(len(ids)))
+
for _, id := range ids {
if err := p.store.Delete(id); err != nil {
log.Error("Failed to delete dropped transaction", "id", id, "err", err)
@@ -1161,7 +1203,7 @@ func (p *BlobPool) Get(hash common.Hash) *types.Transaction {
}
// Add inserts a set of blob transactions into the pool if they pass validation (both
-// consensus validity and pool restictions).
+// consensus validity and pool restrictions).
func (p *BlobPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
var (
adds = make([]*types.Transaction, 0, len(txs))
@@ -1181,10 +1223,10 @@ func (p *BlobPool) Add(txs []*types.Transaction, local bool, sync bool) []error
}
// Add inserts a new blob transaction into the pool if it passes validation (both
-// consensus validity and pool restictions).
+// consensus validity and pool restrictions).
func (p *BlobPool) add(tx *types.Transaction) (err error) {
// The blob pool blocks on adding a transaction. This is because blob txs are
- // only even pulled form the network, so this method will act as the overload
+ // only even pulled from the network, so this method will act as the overload
// protection for fetches.
waitStart := time.Now()
p.lock.Lock()
@@ -1198,6 +1240,22 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
// Ensure the transaction is valid from all perspectives
if err := p.validateTx(tx); err != nil {
log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err)
+ switch {
+ case errors.Is(err, txpool.ErrUnderpriced):
+ addUnderpricedMeter.Mark(1)
+ case errors.Is(err, core.ErrNonceTooLow):
+ addStaleMeter.Mark(1)
+ case errors.Is(err, core.ErrNonceTooHigh):
+ addGappedMeter.Mark(1)
+ case errors.Is(err, core.ErrInsufficientFunds):
+ addOverdraftedMeter.Mark(1)
+ case errors.Is(err, txpool.ErrAccountLimitExceeded):
+ addOvercappedMeter.Mark(1)
+ case errors.Is(err, txpool.ErrReplaceUnderpriced):
+ addNoreplaceMeter.Mark(1)
+ default:
+ addInvalidMeter.Mark(1)
+ }
return err
}
// If the address is not yet known, request exclusivity to track the account
@@ -1205,6 +1263,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
from, _ := types.Sender(p.signer, tx) // already validated above
if _, ok := p.index[from]; !ok {
if err := p.reserve(from, true); err != nil {
+ addNonExclusiveMeter.Mark(1)
return err
}
defer func() {
@@ -1244,6 +1303,8 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
}
if len(p.index[from]) > offset {
// Transaction replaces a previously queued one
+ dropReplacedMeter.Mark(1)
+
prev := p.index[from][offset]
if err := p.store.Delete(prev.id); err != nil {
// Shitty situation, but try to recover gracefully instead of going boom
@@ -1322,6 +1383,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
}
p.updateStorageMetrics()
+ addValidMeter.Mark(1)
return nil
}
@@ -1355,7 +1417,7 @@ func (p *BlobPool) drop() {
p.stored -= uint64(drop.size)
delete(p.lookup, drop.hash)
- // Remove the transaction from the pool's evicion heap:
+ // Remove the transaction from the pool's eviction heap:
// - If the entire account was dropped, pop off the address
// - Otherwise, if the new tail has better eviction caps, fix the heap
if last {
@@ -1371,7 +1433,9 @@ func (p *BlobPool) drop() {
}
}
// Remove the transaction from the data store
- log.Warn("Evicting overflown blob transaction", "from", from, "evicted", drop.nonce, "id", drop.id)
+ log.Debug("Evicting overflown blob transaction", "from", from, "evicted", drop.nonce, "id", drop.id)
+ dropOverflownMeter.Mark(1)
+
if err := p.store.Delete(drop.id); err != nil {
log.Error("Failed to drop evicted transaction", "id", drop.id, "err", err)
}
@@ -1379,7 +1443,15 @@ func (p *BlobPool) drop() {
// Pending retrieves all currently processable transactions, grouped by origin
// account and sorted by nonce.
-func (p *BlobPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction {
+//
+// The transactions can also be pre-filtered by the dynamic fee components to
+// reduce allocations and load on downstream subsystems.
+func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
+ // If only plain transactions are requested, this pool is unsuitable as it
+ // contains none, don't even bother.
+ if filter.OnlyPlainTxs {
+ return nil
+ }
// Track the amount of time waiting to retrieve the list of pending blob txs
// from the pool and the amount of time actually spent on assembling the data.
// The latter will be pretty much moot, but we've kept it to have symmetric
@@ -1389,20 +1461,40 @@ func (p *BlobPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTr
pendwaitHist.Update(time.Since(pendStart).Nanoseconds())
defer p.lock.RUnlock()
- defer func(start time.Time) {
- pendtimeHist.Update(time.Since(start).Nanoseconds())
- }(time.Now())
+ execStart := time.Now()
+ defer func() {
+ pendtimeHist.Update(time.Since(execStart).Nanoseconds())
+ }()
- pending := make(map[common.Address][]*txpool.LazyTransaction)
+ pending := make(map[common.Address][]*txpool.LazyTransaction, len(p.index))
for addr, txs := range p.index {
- var lazies []*txpool.LazyTransaction
+ lazies := make([]*txpool.LazyTransaction, 0, len(txs))
for _, tx := range txs {
+ // If transaction filtering was requested, discard badly priced ones
+ if filter.MinTip != nil && filter.BaseFee != nil {
+ if tx.execFeeCap.Lt(filter.BaseFee) {
+ break // basefee too low, cannot be included, discard rest of txs from the account
+ }
+ tip := new(uint256.Int).Sub(tx.execFeeCap, filter.BaseFee)
+ if tip.Gt(tx.execTipCap) {
+ tip = tx.execTipCap
+ }
+ if tip.Lt(filter.MinTip) {
+ break // allowed or remaining tip too low, cannot be included, discard rest of txs from the account
+ }
+ }
+ if filter.BlobFee != nil {
+ if tx.blobFeeCap.Lt(filter.BlobFee) {
+ break // blobfee too low, cannot be included, discard rest of txs from the account
+ }
+ }
+ // Transaction was accepted according to the filter, append to the pending list
lazies = append(lazies, &txpool.LazyTransaction{
Pool: p,
Hash: tx.hash,
- Time: time.Now(), // TODO(karalabe): Maybe save these and use that?
- GasFeeCap: tx.execFeeCap.ToBig(),
- GasTipCap: tx.execTipCap.ToBig(),
+ Time: execStart, // TODO(karalabe): Maybe save these and use that?
+ GasFeeCap: tx.execFeeCap,
+ GasTipCap: tx.execTipCap,
Gas: tx.execGas,
BlobGas: tx.blobGas,
})
@@ -1462,7 +1554,7 @@ func (p *BlobPool) updateStorageMetrics() {
}
// updateLimboMetrics retrieves a bunch of stats from the limbo store and pushes
-// // them out as metrics.
+// them out as metrics.
func (p *BlobPool) updateLimboMetrics() {
stats := p.limbo.store.Infos()
diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go
index 07388905c0..2845bf4160 100644
--- a/core/txpool/blobpool/blobpool_test.go
+++ b/core/txpool/blobpool/blobpool_test.go
@@ -50,21 +50,9 @@ var (
emptyBlob = kzg4844.Blob{}
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
- emptyBlobVHash = blobHash(emptyBlobCommit)
+ emptyBlobVHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
)
-func blobHash(commit kzg4844.Commitment) common.Hash {
- hasher := sha256.New()
- hasher.Write(commit[:])
- hash := hasher.Sum(nil)
-
- var vhash common.Hash
- vhash[0] = params.BlobTxHashVersion
- copy(vhash[1:], hash[1:])
-
- return vhash
-}
-
// Chain configuration with Cancun enabled.
//
// TODO(karalabe): replace with params.MainnetChainConfig after Cancun.
@@ -201,7 +189,7 @@ func makeTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64,
return types.MustSignNewTx(key, types.LatestSigner(testChainConfig), blobtx)
}
-// makeUnsignedTx is a utility method to construct a random blob tranasaction
+// makeUnsignedTx is a utility method to construct a random blob transaction
// without signing it.
func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64) *types.BlobTx {
return &types.BlobTx{
@@ -321,7 +309,16 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
// - 1. A transaction that cannot be decoded must be dropped
// - 2. A transaction that cannot be recovered (bad signature) must be dropped
// - 3. All transactions after a nonce gap must be dropped
-// - 4. All transactions after an underpriced one (including it) must be dropped
+// - 4. All transactions after an already included nonce must be dropped
+// - 5. All transactions after an underpriced one (including it) must be dropped
+// - 6. All transactions after an overdrafting sequence must be dropped
+// - 7. All transactions exceeding the per-account limit must be dropped
+//
+// Furthermore, some strange corner-cases can also occur after a crash, as Billy's
+// simplicity also allows it to resurrect past deleted entities:
+//
+// - 8. Fully duplicate transactions (matching hash) must be dropped
+// - 9. Duplicate nonces from the same account must be dropped
func TestOpenDrops(t *testing.T) {
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
@@ -354,7 +351,7 @@ func TestOpenDrops(t *testing.T) {
badsig, _ := store.Put(blob)
// Insert a sequence of transactions with a nonce gap in between to verify
- // that anything gapped will get evicted (case 3)
+ // that anything gapped will get evicted (case 3).
var (
gapper, _ = crypto.GenerateKey()
@@ -373,7 +370,7 @@ func TestOpenDrops(t *testing.T) {
}
}
// Insert a sequence of transactions with a gapped starting nonce to verify
- // that the entire set will get dropped.
+ // that the entire set will get dropped (case 3).
var (
dangler, _ = crypto.GenerateKey()
dangling = make(map[uint64]struct{})
@@ -386,7 +383,7 @@ func TestOpenDrops(t *testing.T) {
dangling[id] = struct{}{}
}
// Insert a sequence of transactions with already passed nonces to veirfy
- // that the entire set will get dropped.
+ // that the entire set will get dropped (case 4).
var (
filler, _ = crypto.GenerateKey()
filled = make(map[uint64]struct{})
@@ -398,8 +395,8 @@ func TestOpenDrops(t *testing.T) {
id, _ := store.Put(blob)
filled[id] = struct{}{}
}
- // Insert a sequence of transactions with partially passed nonces to veirfy
- // that the included part of the set will get dropped
+ // Insert a sequence of transactions with partially passed nonces to verify
+ // that the included part of the set will get dropped (case 4).
var (
overlapper, _ = crypto.GenerateKey()
overlapped = make(map[uint64]struct{})
@@ -416,7 +413,7 @@ func TestOpenDrops(t *testing.T) {
}
}
// Insert a sequence of transactions with an underpriced first to verify that
- // the entire set will get dropped (case 4).
+ // the entire set will get dropped (case 5).
var (
underpayer, _ = crypto.GenerateKey()
underpaid = make(map[uint64]struct{})
@@ -435,7 +432,7 @@ func TestOpenDrops(t *testing.T) {
}
// Insert a sequence of transactions with an underpriced in between to verify
- // that it and anything newly gapped will get evicted (case 4).
+ // that it and anything newly gapped will get evicted (case 5).
var (
outpricer, _ = crypto.GenerateKey()
outpriced = make(map[uint64]struct{})
@@ -457,7 +454,7 @@ func TestOpenDrops(t *testing.T) {
}
}
// Insert a sequence of transactions fully overdrafted to verify that the
- // entire set will get invalidated.
+ // entire set will get invalidated (case 6).
var (
exceeder, _ = crypto.GenerateKey()
exceeded = make(map[uint64]struct{})
@@ -475,7 +472,7 @@ func TestOpenDrops(t *testing.T) {
exceeded[id] = struct{}{}
}
// Insert a sequence of transactions partially overdrafted to verify that part
- // of the set will get invalidated.
+ // of the set will get invalidated (case 6).
var (
overdrafter, _ = crypto.GenerateKey()
overdrafted = make(map[uint64]struct{})
@@ -497,7 +494,7 @@ func TestOpenDrops(t *testing.T) {
}
}
// Insert a sequence of transactions overflowing the account cap to verify
- // that part of the set will get invalidated.
+ // that part of the set will get invalidated (case 7).
var (
overcapper, _ = crypto.GenerateKey()
overcapped = make(map[uint64]struct{})
@@ -512,21 +509,59 @@ func TestOpenDrops(t *testing.T) {
overcapped[id] = struct{}{}
}
}
+ // Insert a batch of duplicated transactions to verify that only one of each
+ // version will remain (case 8).
+ var (
+ duplicater, _ = crypto.GenerateKey()
+ duplicated = make(map[uint64]struct{})
+ )
+ for _, nonce := range []uint64{0, 1, 2} {
+ blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, 1, 1, duplicater))
+
+ for i := 0; i < int(nonce)+1; i++ {
+ id, _ := store.Put(blob)
+ if i == 0 {
+ valids[id] = struct{}{}
+ } else {
+ duplicated[id] = struct{}{}
+ }
+ }
+ }
+ // Insert a batch of duplicated nonces to verify that only one of each will
+ // remain (case 9).
+ var (
+ repeater, _ = crypto.GenerateKey()
+ repeated = make(map[uint64]struct{})
+ )
+ for _, nonce := range []uint64{0, 1, 2} {
+ for i := 0; i < int(nonce)+1; i++ {
+ blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, uint64(i)+1 /* unique hashes */, 1, repeater))
+
+ id, _ := store.Put(blob)
+ if i == 0 {
+ valids[id] = struct{}{}
+ } else {
+ repeated[id] = struct{}{}
+ }
+ }
+ }
store.Close()
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), big.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000))
statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3)
- statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), big.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000))
statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2)
- statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), big.NewInt(10000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), uint256.NewInt(10000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(duplicater.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(repeater.PublicKey), uint256.NewInt(1000000))
statedb.Commit(0, true)
chain := &testBlockChain{
@@ -536,7 +571,7 @@ func TestOpenDrops(t *testing.T) {
statedb: statedb,
}
pool := New(Config{Datadir: storage}, chain)
- if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
}
defer pool.Close()
@@ -570,6 +605,10 @@ func TestOpenDrops(t *testing.T) {
t.Errorf("partially overdrafted transaction remained in storage: %d", tx.id)
} else if _, ok := overcapped[tx.id]; ok {
t.Errorf("overcapped transaction remained in storage: %d", tx.id)
+ } else if _, ok := duplicated[tx.id]; ok {
+ t.Errorf("duplicated transaction remained in storage: %d", tx.id)
+ } else if _, ok := repeated[tx.id]; ok {
+ t.Errorf("repeated nonce transaction remained in storage: %d", tx.id)
} else {
alive[tx.id] = struct{}{}
}
@@ -614,7 +653,7 @@ func TestOpenIndex(t *testing.T) {
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
// Insert a sequence of transactions with varying price points to check that
- // the cumulative minimumw will be maintained.
+ // the cumulative minimum will be maintained.
var (
key, _ = crypto.GenerateKey()
addr = crypto.PubkeyToAddress(key.PublicKey)
@@ -641,7 +680,7 @@ func TestOpenIndex(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr, uint256.NewInt(1_000_000_000))
statedb.Commit(0, true)
chain := &testBlockChain{
@@ -651,7 +690,7 @@ func TestOpenIndex(t *testing.T) {
statedb: statedb,
}
pool := New(Config{Datadir: storage}, chain)
- if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
}
defer pool.Close()
@@ -741,9 +780,9 @@ func TestOpenHeap(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000))
statedb.Commit(0, true)
chain := &testBlockChain{
@@ -753,7 +792,7 @@ func TestOpenHeap(t *testing.T) {
statedb: statedb,
}
pool := New(Config{Datadir: storage}, chain)
- if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
}
defer pool.Close()
@@ -821,9 +860,9 @@ func TestOpenCap(t *testing.T) {
for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} {
// Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000))
statedb.Commit(0, true)
chain := &testBlockChain{
@@ -833,7 +872,7 @@ func TestOpenCap(t *testing.T) {
statedb: statedb,
}
pool := New(Config{Datadir: storage, Datacap: datacap}, chain)
- if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
}
// Verify that enough transactions have been dropped to get the pool's size
@@ -1193,6 +1232,24 @@ func TestAdd(t *testing.T) {
},
},
},
+ // Blob transactions that don't meet the min blob gas price should be rejected
+ {
+ seeds: map[string]seed{
+ "alice": {balance: 10000000},
+ },
+ adds: []addtx{
+ { // New account, no previous txs, nonce 0, but blob fee cap too low
+ from: "alice",
+ tx: makeUnsignedTx(0, 1, 1, 0),
+ err: txpool.ErrUnderpriced,
+ },
+ { // Same as above but blob fee cap equals minimum, should be accepted
+ from: "alice",
+ tx: makeUnsignedTx(0, 1, 1, params.BlobTxMinBlobGasprice),
+ err: nil,
+ },
+ },
+ },
}
for i, tt := range tests {
// Create a temporary folder for the persistent backend
@@ -1214,7 +1271,7 @@ func TestAdd(t *testing.T) {
addrs[acc] = crypto.PubkeyToAddress(keys[acc].PublicKey)
// Seed the state database with this account
- statedb.AddBalance(addrs[acc], new(big.Int).SetUint64(seed.balance))
+ statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance))
statedb.SetNonce(addrs[acc], seed.nonce)
// Sign the seed transactions and store them in the data store
@@ -1235,7 +1292,7 @@ func TestAdd(t *testing.T) {
statedb: statedb,
}
pool := New(Config{Datadir: storage}, chain)
- if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
t.Fatalf("test %d: failed to create blob pool: %v", i, err)
}
verifyPoolInternals(t, pool)
@@ -1253,3 +1310,65 @@ func TestAdd(t *testing.T) {
pool.Close()
}
}
+
+// Benchmarks the time it takes to assemble the lazy pending transaction list
+// from the pool contents.
+func BenchmarkPoolPending100Mb(b *testing.B) { benchmarkPoolPending(b, 100_000_000) }
+func BenchmarkPoolPending1GB(b *testing.B) { benchmarkPoolPending(b, 1_000_000_000) }
+func BenchmarkPoolPending10GB(b *testing.B) { benchmarkPoolPending(b, 10_000_000_000) }
+
+func benchmarkPoolPending(b *testing.B, datacap uint64) {
+ // Calculate the maximum number of transaction that would fit into the pool
+ // and generate a set of random accounts to seed them with.
+ capacity := datacap / params.BlobTxBlobGasPerBlob
+
+ var (
+ basefee = uint64(1050)
+ blobfee = uint64(105)
+ signer = types.LatestSigner(testChainConfig)
+ statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
+ chain = &testBlockChain{
+ config: testChainConfig,
+ basefee: uint256.NewInt(basefee),
+ blobfee: uint256.NewInt(blobfee),
+ statedb: statedb,
+ }
+ pool = New(Config{Datadir: ""}, chain)
+ )
+
+ if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
+ b.Fatalf("failed to create blob pool: %v", err)
+ }
+ // Fill the pool up with one random transaction from each account with the
+ // same price and everything to maximize the worst case scenario
+ for i := 0; i < int(capacity); i++ {
+ blobtx := makeUnsignedTx(0, 10, basefee+10, blobfee)
+ blobtx.R = uint256.NewInt(1)
+ blobtx.S = uint256.NewInt(uint64(100 + i))
+ blobtx.V = uint256.NewInt(0)
+ tx := types.NewTx(blobtx)
+ addr, err := types.Sender(signer, tx)
+ if err != nil {
+ b.Fatal(err)
+ }
+ statedb.AddBalance(addr, uint256.NewInt(1_000_000_000))
+ pool.add(tx)
+ }
+ statedb.Commit(0, true)
+ defer pool.Close()
+
+ // Benchmark assembling the pending
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ p := pool.Pending(txpool.PendingFilter{
+ MinTip: uint256.NewInt(1),
+ BaseFee: chain.basefee,
+ BlobFee: chain.blobfee,
+ })
+ if len(p) != int(capacity) {
+ b.Fatalf("have %d want %d", len(p), capacity)
+ }
+ }
+}
diff --git a/core/txpool/blobpool/config.go b/core/txpool/blobpool/config.go
index 99a2002a30..1d180739cd 100644
--- a/core/txpool/blobpool/config.go
+++ b/core/txpool/blobpool/config.go
@@ -30,8 +30,8 @@ type Config struct {
// DefaultConfig contains the default configurations for the transaction pool.
var DefaultConfig = Config{
Datadir: "blobpool",
- Datacap: 10 * 1024 * 1024 * 1024,
- PriceBump: 100, // either have patience or be aggressive, no mushy ground
+ Datacap: 10 * 1024 * 1024 * 1024 / 4, // TODO(karalabe): /4 handicap for rollout, gradually bump back up to 10GB
+ PriceBump: 100, // either have patience or be aggressive, no mushy ground
}
// sanitize checks the provided user configurations and changes anything that's
diff --git a/core/txpool/blobpool/evictheap.go b/core/txpool/blobpool/evictheap.go
index df594099f7..bc4543a352 100644
--- a/core/txpool/blobpool/evictheap.go
+++ b/core/txpool/blobpool/evictheap.go
@@ -30,7 +30,7 @@ import (
// transaction from each account to determine which account to evict from.
//
// The heap internally tracks a slice of cheapest transactions from each account
-// and a mapping from addresses to indices for direct removals/udates.
+// and a mapping from addresses to indices for direct removals/updates.
//
// The goal of the heap is to decide which account has the worst bottleneck to
// evict transactions from.
diff --git a/core/txpool/blobpool/metrics.go b/core/txpool/blobpool/metrics.go
index 587804cc61..52419ade09 100644
--- a/core/txpool/blobpool/metrics.go
+++ b/core/txpool/blobpool/metrics.go
@@ -65,8 +65,8 @@ var (
pooltipGauge = metrics.NewRegisteredGauge("blobpool/pooltip", nil)
// addwait/time, resetwait/time and getwait/time track the rough health of
- // the pool and whether or not it's capable of keeping up with the load from
- // the network.
+ // the pool and whether it's capable of keeping up with the load from the
+ // network.
addwaitHist = metrics.NewRegisteredHistogram("blobpool/addwait", nil, metrics.NewExpDecaySample(1028, 0.015))
addtimeHist = metrics.NewRegisteredHistogram("blobpool/addtime", nil, metrics.NewExpDecaySample(1028, 0.015))
getwaitHist = metrics.NewRegisteredHistogram("blobpool/getwait", nil, metrics.NewExpDecaySample(1028, 0.015))
@@ -75,4 +75,31 @@ var (
pendtimeHist = metrics.NewRegisteredHistogram("blobpool/pendtime", nil, metrics.NewExpDecaySample(1028, 0.015))
resetwaitHist = metrics.NewRegisteredHistogram("blobpool/resetwait", nil, metrics.NewExpDecaySample(1028, 0.015))
resettimeHist = metrics.NewRegisteredHistogram("blobpool/resettime", nil, metrics.NewExpDecaySample(1028, 0.015))
+
+ // The below metrics track various cases where transactions are dropped out
+ // of the pool. Most are exceptional, some are chain progression and some
+ // threshold cappings.
+ dropInvalidMeter = metrics.NewRegisteredMeter("blobpool/drop/invalid", nil) // Invalid transaction, consensus change or bugfix, neutral-ish
+ dropDanglingMeter = metrics.NewRegisteredMeter("blobpool/drop/dangling", nil) // First nonce gapped, bad
+ dropFilledMeter = metrics.NewRegisteredMeter("blobpool/drop/filled", nil) // State full-overlap, chain progress, ok
+ dropOverlappedMeter = metrics.NewRegisteredMeter("blobpool/drop/overlapped", nil) // State partial-overlap, chain progress, ok
+ dropRepeatedMeter = metrics.NewRegisteredMeter("blobpool/drop/repeated", nil) // Repeated nonce, bad
+ dropGappedMeter = metrics.NewRegisteredMeter("blobpool/drop/gapped", nil) // Non-first nonce gapped, bad
+ dropOverdraftedMeter = metrics.NewRegisteredMeter("blobpool/drop/overdrafted", nil) // Balance exceeded, bad
+ dropOvercappedMeter = metrics.NewRegisteredMeter("blobpool/drop/overcapped", nil) // Per-account cap exceeded, bad
+ dropOverflownMeter = metrics.NewRegisteredMeter("blobpool/drop/overflown", nil) // Global disk cap exceeded, neutral-ish
+ dropUnderpricedMeter = metrics.NewRegisteredMeter("blobpool/drop/underpriced", nil) // Gas tip changed, neutral
+ dropReplacedMeter = metrics.NewRegisteredMeter("blobpool/drop/replaced", nil) // Transaction replaced, neutral
+
+ // The below metrics track various outcomes of transactions being added to
+ // the pool.
+ addInvalidMeter = metrics.NewRegisteredMeter("blobpool/add/invalid", nil) // Invalid transaction, reject, neutral
+ addUnderpricedMeter = metrics.NewRegisteredMeter("blobpool/add/underpriced", nil) // Gas tip too low, neutral
+ addStaleMeter = metrics.NewRegisteredMeter("blobpool/add/stale", nil) // Nonce already filled, reject, bad-ish
+ addGappedMeter = metrics.NewRegisteredMeter("blobpool/add/gapped", nil) // Nonce gapped, reject, bad-ish
+ addOverdraftedMeter = metrics.NewRegisteredMeter("blobpool/add/overdrafted", nil) // Balance exceeded, reject, neutral
+ addOvercappedMeter = metrics.NewRegisteredMeter("blobpool/add/overcapped", nil) // Per-account cap exceeded, reject, neutral
+ addNoreplaceMeter = metrics.NewRegisteredMeter("blobpool/add/noreplace", nil) // Replacement fees or tips too low, neutral
+ addNonExclusiveMeter = metrics.NewRegisteredMeter("blobpool/add/nonexclusive", nil) // Plain transaction from same account exists, reject, neutral
+ addValidMeter = metrics.NewRegisteredMeter("blobpool/add/valid", nil) // Valid transaction, add, neutral
)
diff --git a/core/txpool/blobpool/priority_test.go b/core/txpool/blobpool/priority_test.go
index 4aad919925..cf0e0454a0 100644
--- a/core/txpool/blobpool/priority_test.go
+++ b/core/txpool/blobpool/priority_test.go
@@ -64,7 +64,7 @@ func BenchmarkDynamicFeeJumpCalculation(b *testing.B) {
// Benchmarks how many priority recalculations can be done.
func BenchmarkPriorityCalculation(b *testing.B) {
// The basefee and blob fee is constant for all transactions across a block,
- // so we can assume theit absolute jump counts can be pre-computed.
+ // so we can assume their absolute jump counts can be pre-computed.
basefee := uint256.NewInt(17_200_000_000) // 17.2 Gwei is the 22.03.2023 zero-emission basefee, random number
blobfee := uint256.NewInt(123_456_789_000) // Completely random, no idea what this will be
diff --git a/core/txpool/errors.go b/core/txpool/errors.go
index 61daa999ff..3a6a913976 100644
--- a/core/txpool/errors.go
+++ b/core/txpool/errors.go
@@ -54,4 +54,10 @@ var (
// 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")
)
diff --git a/core/txpool/legacypool/journal.go b/core/txpool/legacypool/journal.go
index 8fa12ea99f..cb85298851 100644
--- a/core/txpool/legacypool/journal.go
+++ b/core/txpool/legacypool/journal.go
@@ -181,7 +181,11 @@ func (journal *journal) rotate(all map[common.Address]types.Transactions) error
journal.writer = sink
- log.Info("Regenerated local transaction journal", "transactions", journaled, "accounts", len(all))
+ logger := log.Info
+ if len(all) == 0 {
+ logger = log.Debug
+ }
+ logger("Regenerated local transaction journal", "transactions", journaled, "accounts", len(all))
return nil
}
diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go
index 1ffeb54ab1..3e04e69155 100644
--- a/core/txpool/legacypool/legacypool.go
+++ b/core/txpool/legacypool/legacypool.go
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
const (
@@ -210,7 +211,7 @@ type LegacyPool struct {
config Config
chainconfig *params.ChainConfig
chain BlockChain
- gasTip atomic.Pointer[big.Int]
+ gasTip atomic.Pointer[uint256.Int]
txFeed event.Feed
signer types.Signer
mu sync.RWMutex
@@ -302,15 +303,15 @@ func (pool *LegacyPool) Filter(tx *types.Transaction) bool {
// head to allow balance / nonce checks. The transaction journal will be loaded
// from disk and filtered based on the provided starting settings. The internal
// goroutines will be spun up and the pool deemed operational afterwards.
-func (pool *LegacyPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.AddressReserver) error {
+func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error {
// Set the address reserver to request exclusive access to pooled accounts
pool.reserve = reserve
// Set the basic pool parameters
- pool.gasTip.Store(gasTip)
+ pool.gasTip.Store(uint256.NewInt(gasTip))
// Initialize the state with head block, or fallback to empty one in
- // case the head state is not available(might occur when node is not
+ // case the head state is not available (might occur when node is not
// fully synced).
statedb, err := pool.chain.StateAt(head.Root)
if err != nil {
@@ -448,11 +449,13 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
pool.mu.Lock()
defer pool.mu.Unlock()
- old := pool.gasTip.Load()
- pool.gasTip.Store(new(big.Int).Set(tip))
-
+ var (
+ newTip = uint256.MustFromBig(tip)
+ old = pool.gasTip.Load()
+ )
+ pool.gasTip.Store(newTip)
// If the min miner fee increased, remove transactions below the new threshold
- if tip.Cmp(old) > 0 {
+ if newTip.Cmp(old) > 0 {
// pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead
drop := pool.all.RemotesBelowTip(tip)
for _, tx := range drop {
@@ -460,7 +463,7 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
}
pool.priced.Removed(len(drop))
}
- log.Info("Legacy pool tip threshold updated", "tip", tip)
+ log.Info("Legacy pool tip threshold updated", "tip", newTip)
}
// Nonce returns the next nonce of an account, with all transactions executable
@@ -530,24 +533,38 @@ func (pool *LegacyPool) ContentFrom(addr common.Address) ([]*types.Transaction,
}
// Pending retrieves all currently processable transactions, grouped by origin
-// account and sorted by nonce. The returned transaction set is a copy and can be
-// freely modified by calling code.
+// account and sorted by nonce.
//
-// The enforceTips parameter can be used to do an extra filtering on the pending
-// transactions and only return those whose **effective** tip is large enough in
-// the next pending execution environment.
-func (pool *LegacyPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction {
+// The transactions can also be pre-filtered by the dynamic fee components to
+// reduce allocations and load on downstream subsystems.
+func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
+ // If only blob transactions are requested, this pool is unsuitable as it
+ // contains none, don't even bother.
+ if filter.OnlyBlobTxs {
+ return nil
+ }
pool.mu.Lock()
defer pool.mu.Unlock()
+ // Convert the new uint256.Int types to the old big.Int ones used by the legacy pool
+ var (
+ minTipBig *big.Int
+ baseFeeBig *big.Int
+ )
+ if filter.MinTip != nil {
+ minTipBig = filter.MinTip.ToBig()
+ }
+ if filter.BaseFee != nil {
+ baseFeeBig = filter.BaseFee.ToBig()
+ }
pending := make(map[common.Address][]*txpool.LazyTransaction, len(pool.pending))
for addr, list := range pool.pending {
txs := list.Flatten()
// If the miner requests tip enforcement, cap the lists now
- if enforceTips && !pool.locals.contains(addr) {
+ if minTipBig != nil && !pool.locals.contains(addr) {
for i, tx := range txs {
- if tx.EffectiveGasTipIntCmp(pool.gasTip.Load(), pool.priced.urgent.baseFee) < 0 {
+ if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 {
txs = txs[:i]
break
}
@@ -561,8 +578,8 @@ func (pool *LegacyPool) Pending(enforceTips bool) map[common.Address][]*txpool.L
Hash: txs[i].Hash(),
Tx: txs[i],
Time: txs[i].Time(),
- GasFeeCap: txs[i].GasFeeCap(),
- GasTipCap: txs[i].GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(txs[i].GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(txs[i].GasTipCap()),
Gas: txs[i].Gas(),
BlobGas: txs[i].BlobGas(),
}
@@ -610,7 +627,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro
1<= b.N/2 {
close(done)
@@ -3157,7 +3153,7 @@ func BenchmarkPoolAccountsBatchInsert(b *testing.B) {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
tx := transaction(uint64(0), 100000, key)
@@ -3185,7 +3181,7 @@ func BenchmarkPoolAccountsBatchInsertRace(b *testing.B) {
account := crypto.PubkeyToAddress(key.PublicKey)
tx := transaction(uint64(0), 100000, key)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
batches[i] = tx
}
@@ -3202,7 +3198,7 @@ func BenchmarkPoolAccountsBatchInsertRace(b *testing.B) {
for {
select {
case <-t.C:
- pending = pool.Pending(true)
+ pending = pool.Pending(txpool.PendingFilter{})
case <-done:
break loop
}
@@ -3237,7 +3233,7 @@ func BenchmarkPoolAccountsBatchInsertNoLockRace(b *testing.B) {
account := crypto.PubkeyToAddress(key.PublicKey)
tx := transaction(uint64(0), 100000, key)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
batches[i] = tx
}
@@ -3251,7 +3247,7 @@ func BenchmarkPoolAccountsBatchInsertNoLockRace(b *testing.B) {
var pending map[common.Address][]*txpool.LazyTransaction
for range t.C {
- pending = pool.Pending(true)
+ pending = pool.Pending(txpool.PendingFilter{})
if len(pending) >= b.N/2 {
close(done)
@@ -3300,7 +3296,7 @@ func TestPoolMultiAccountBatchInsertRace(t *testing.T) {
)
for range t.C {
- pending = pool.Pending(true)
+ pending = pool.Pending(txpool.PendingFilter{})
total = len(pending)
_ = pool.Locals()
@@ -3329,7 +3325,7 @@ func newTxs(pool *LegacyPool) *types.Transaction {
account := crypto.PubkeyToAddress(key.PublicKey)
tx := transaction(uint64(0), 100000, key)
- pool.currentState.AddBalance(account, big.NewInt(1_000_000_000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1_000_000_000))
return tx
}
@@ -4787,8 +4783,7 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) {
for i := 0; i < b.N; i++ {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
-
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
tx := transaction(uint64(0), 100000, key)
batches[i] = tx
}
diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go
index f68cf72d89..3c6b028f7f 100644
--- a/core/txpool/legacypool/list.go
+++ b/core/txpool/legacypool/list.go
@@ -29,6 +29,8 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
+ "github.com/holiman/uint256"
+ "golang.org/x/exp/slices"
)
// nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
@@ -208,7 +210,7 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
// Otherwise gather and drop the highest nonce'd transactions
var drops types.Transactions
- sort.Sort(*m.index)
+ slices.Sort(*m.index)
for size := len(m.items); size > threshold; size-- {
drops = append(drops, m.items[(*m.index)[size-1]])
@@ -216,7 +218,8 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
}
*m.index = (*m.index)[:threshold]
- heap.Init(m.index)
+ // The sorted m.index slice is still a valid heap, so there is no need to
+ // reheap after deleting tail items.
// If we had a cache, shift the back
m.cacheMu.Lock()
@@ -404,19 +407,19 @@ type list struct {
strict bool // Whether nonces are strictly continuous or not
txs *sortedMap // Heap indexed sorted hash map of the transactions
- costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
- gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
- totalcost *big.Int // Total cost of all transactions in the list
+ costcap *uint256.Int // Price of the highest costing transaction (reset only if exceeds balance)
+ gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
+ totalcost *uint256.Int // Total cost of all transactions in the list
}
-// newList create a new transaction list for maintaining nonce-indexable fast,
+// newList creates a new transaction list for maintaining nonce-indexable fast,
// gapped, sortable transaction lists.
func newList(strict bool) *list {
return &list{
strict: strict,
txs: newSortedMap(),
- costcap: new(big.Int),
- totalcost: new(big.Int),
+ costcap: new(uint256.Int),
+ totalcost: new(uint256.Int),
}
}
@@ -458,10 +461,15 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa
l.subTotalCost([]*types.Transaction{old})
}
// Add new tx cost to totalcost
- l.totalcost.Add(l.totalcost, tx.Cost())
+ cost, overflow := uint256.FromBig(tx.Cost())
+ if overflow {
+ return false, nil
+ }
+ l.totalcost.Add(l.totalcost, cost)
+
// Otherwise overwrite the old transaction with the current one
l.txs.Put(tx)
- if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
+ if l.costcap.Cmp(cost) < 0 {
l.costcap = cost
}
if gas := tx.Gas(); l.gascap < gas {
@@ -489,17 +497,17 @@ func (l *list) Forward(threshold uint64) types.Transactions {
// a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions.
-func (l *list) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
+func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil
}
- l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
+ l.costcap = new(uint256.Int).Set(costLimit) // Lower the caps to the thresholds
l.gascap = gasLimit
// Filter out all the transactions above the account's funds
removed := l.txs.Filter(func(tx *types.Transaction) bool {
- return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit) > 0
+ return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit.ToBig()) > 0
})
if len(removed) == 0 {
@@ -625,7 +633,10 @@ func (l *list) Has(nonce uint64) bool {
// total cost of all transactions.
func (l *list) subTotalCost(txs []*types.Transaction) {
for _, tx := range txs {
- l.totalcost.Sub(l.totalcost, tx.Cost())
+ _, underflow := l.totalcost.SubOverflow(l.totalcost, uint256.MustFromBig(tx.Cost()))
+ if underflow {
+ panic("totalcost underflow")
+ }
}
}
diff --git a/core/txpool/legacypool/list_test.go b/core/txpool/legacypool/list_test.go
index 86bd9e1957..80018de5c1 100644
--- a/core/txpool/legacypool/list_test.go
+++ b/core/txpool/legacypool/list_test.go
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/holiman/uint256"
)
// Tests that transactions can be added to strict lists and list contents and
@@ -59,6 +60,21 @@ func TestStrictListAdd(t *testing.T) {
}
}
+// TestListAddVeryExpensive tests adding txs which exceed 256 bits in cost. It is
+// expected that the list does not panic.
+func TestListAddVeryExpensive(t *testing.T) {
+ key, _ := crypto.GenerateKey()
+ list := newList(true)
+ for i := 0; i < 3; i++ {
+ value := big.NewInt(100)
+ gasprice, _ := new(big.Int).SetString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0)
+ gaslimit := uint64(i)
+ tx, _ := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, value, gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
+ t.Logf("cost: %x bitlen: %d\n", tx.Cost(), tx.Cost().BitLen())
+ list.Add(tx, DefaultConfig.PriceBump)
+ }
+}
+
func BenchmarkListAdd(b *testing.B) {
// Generate a list of transactions to insert
key, _ := crypto.GenerateKey()
@@ -68,7 +84,7 @@ func BenchmarkListAdd(b *testing.B) {
txs[i] = transaction(uint64(i), 0, key)
}
// Insert the transactions in a random order
- priceLimit := big.NewInt(int64(DefaultConfig.PriceLimit))
+ priceLimit := uint256.NewInt(DefaultConfig.PriceLimit)
b.ResetTimer()
for i := 0; i < b.N; i++ {
list := newList(true)
@@ -138,3 +154,25 @@ func TestFilterTxConditional(t *testing.T) {
require.Equal(t, tx2, drops[0], "Got %x, expected %x", drops[0].Hash(), tx2.Hash())
}
+
+func BenchmarkListCapOneTx(b *testing.B) {
+ // Generate a list of transactions to insert
+ key, _ := crypto.GenerateKey()
+
+ txs := make(types.Transactions, 32)
+ for i := 0; i < len(txs); i++ {
+ txs[i] = transaction(uint64(i), 0, key)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ list := newList(true)
+ // Insert the transactions in a random order
+ for _, v := range rand.Perm(len(txs)) {
+ list.Add(txs[v], DefaultConfig.PriceBump)
+ }
+ b.StartTimer()
+ list.Cap(list.Len() - 1)
+ b.StopTimer()
+ }
+}
diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go
index 554404a57c..9881ed1b8f 100644
--- a/core/txpool/subpool.go
+++ b/core/txpool/subpool.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
+ "github.com/holiman/uint256"
)
// LazyTransaction contains a small subset of the transaction properties that is
@@ -34,9 +35,9 @@ type LazyTransaction struct {
Hash common.Hash // Transaction hash to pull up if needed
Tx *types.Transaction // Transaction if already resolved
- Time time.Time // Time when the transaction was first seen
- GasFeeCap *big.Int // Maximum fee per gas the transaction may consume
- GasTipCap *big.Int // Maximum miner tip per gas the transaction can pay
+ Time time.Time // Time when the transaction was first seen
+ GasFeeCap *uint256.Int // Maximum fee per gas the transaction may consume
+ GasTipCap *uint256.Int // Maximum miner tip per gas the transaction can pay
Gas uint64 // Amount of gas required by the transaction
BlobGas uint64 // Amount of blob gas required by the transaction
@@ -44,11 +45,17 @@ type LazyTransaction struct {
// Resolve retrieves the full transaction belonging to a lazy handle if it is still
// maintained by the transaction pool.
+//
+// Note, the method will *not* cache the retrieved transaction if the original
+// pool has not cached it. The idea being, that if the tx was too big to insert
+// originally, silently saving it will cause more trouble down the line (and
+// indeed seems to have caused a memory bloat in the original implementation
+// which did just that).
func (ltx *LazyTransaction) Resolve() *types.Transaction {
- if ltx.Tx == nil {
- ltx.Tx = ltx.Pool.Get(ltx.Hash)
+ if ltx.Tx != nil {
+ return ltx.Tx
}
- return ltx.Tx
+ return ltx.Pool.Get(ltx.Hash)
}
// LazyResolver is a minimal interface needed for a transaction pool to satisfy
@@ -63,6 +70,21 @@ type LazyResolver interface {
// may request (and relinquish) exclusive access to certain addresses.
type AddressReserver func(addr common.Address, reserve bool) error
+// PendingFilter is a collection of filter rules to allow retrieving a subset
+// of transactions for announcement or mining.
+//
+// Note, the entries here are not arbitrary useful filters, rather each one has
+// a very specific call site in mind and each one can be evaluated very cheaply
+// by the pool implementations. Only add new ones that satisfy those constraints.
+type PendingFilter struct {
+ MinTip *uint256.Int // Minimum miner tip required to include a transaction
+ BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction
+ BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction
+
+ OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling)
+ OnlyBlobTxs bool // Return only blob transactions (block blob-space filling)
+}
+
// SubPool represents a specialized transaction pool that lives on its own (e.g.
// blob pool). Since independent of how many specialized pools we have, they do
// need to be updated in lockstep and assemble into one coherent view for block
@@ -80,7 +102,7 @@ type SubPool interface {
// These should not be passed as a constructor argument - nor should the pools
// start by themselves - in order to keep multiple subpools in lockstep with
// one another.
- Init(gasTip *big.Int, head *types.Header, reserve AddressReserver) error
+ Init(gasTip uint64, head *types.Header, reserve AddressReserver) error
// Close terminates any background processing threads and releases any held
// resources.
@@ -108,7 +130,10 @@ type SubPool interface {
// Pending retrieves all currently processable transactions, grouped by origin
// account and sorted by nonce.
- Pending(enforceTips bool) map[common.Address][]*LazyTransaction
+ //
+ // The transactions can also be pre-filtered by the dynamic fee components to
+ // reduce allocations and load on downstream subsystems.
+ Pending(filter PendingFilter) map[common.Address][]*LazyTransaction
// SubscribeTransactions subscribes to new transaction events. The subscriber
// can decide whether to receive notifications only for newly seen transactions
diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go
index 0d4e05da4c..be7435247d 100644
--- a/core/txpool/txpool.go
+++ b/core/txpool/txpool.go
@@ -72,11 +72,14 @@ type TxPool struct {
subs event.SubscriptionScope // Subscription scope to unsubscribe all on shutdown
quit chan chan error // Quit channel to tear down the head updater
+ term chan struct{} // Termination channel to detect a closed pool
+
+ sync chan chan error // Testing / simulator channel to block until internal reset is done
}
// New creates a new transaction pool to gather, sort and filter inbound
// transactions from the network.
-func New(gasTip *big.Int, chain BlockChain, subpools []SubPool) (*TxPool, error) {
+func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) {
// Retrieve the current head so that all subpools and this main coordinator
// pool will have the same starting state, even if the chain moves forward
// during initialization.
@@ -86,6 +89,8 @@ func New(gasTip *big.Int, chain BlockChain, subpools []SubPool) (*TxPool, error)
subpools: subpools,
reservations: make(map[common.Address]SubPool),
quit: make(chan chan error),
+ term: make(chan struct{}),
+ sync: make(chan chan error),
}
for i, subpool := range subpools {
if err := subpool.Init(gasTip, head, pool.reserver(i, subpool)); err != nil {
@@ -117,7 +122,7 @@ func (p *TxPool) reserver(id int, subpool SubPool) AddressReserver {
log.Error("pool attempted to reserve already-owned address", "address", addr)
return nil // Ignore fault to give the pool a chance to recover while the bug gets fixed
}
- return errors.New("address already reserved")
+ return ErrAlreadyReserved
}
p.reservations[addr] = subpool
if metrics.Enabled {
@@ -174,6 +179,9 @@ func (p *TxPool) Close() error {
// outside blockchain events as well as for various reporting and transaction
// eviction events.
func (p *TxPool) loop(head *types.Header, chain BlockChain) {
+ // Close the termination marker when the pool stops
+ defer close(p.term)
+
// Subscribe to chain head events to trigger subpool resets
var (
newHeadCh = make(chan core.ChainHeadEvent)
@@ -190,13 +198,23 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
var (
resetBusy = make(chan struct{}, 1) // Allow 1 reset to run concurrently
resetDone = make(chan *types.Header)
+
+ resetForced bool // Whether a forced reset was requested, only used in simulator mode
+ resetWaiter chan error // Channel waiting on a forced reset, only used in simulator mode
)
+ // Notify the live reset waiter to not block if the txpool is closed.
+ defer func() {
+ if resetWaiter != nil {
+ resetWaiter <- errors.New("pool already terminated")
+ resetWaiter = nil
+ }
+ }()
var errc chan error
for errc == nil {
// Something interesting might have happened, run a reset if there is
// one needed but none is running. The resetter will run on its own
// goroutine to allow chain head events to be consumed contiguously.
- if newHead != oldHead {
+ if newHead != oldHead || resetForced {
// Try to inject a busy marker and start a reset if successful
select {
case resetBusy <- struct{}{}:
@@ -208,8 +226,17 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
resetDone <- newHead
}(oldHead, newHead)
+ // If the reset operation was explicitly requested, consider it
+ // being fulfilled and drop the request marker. If it was not,
+ // this is a noop.
+ resetForced = false
+
default:
- // Reset already running, wait until it finishes
+ // Reset already running, wait until it finishes.
+ //
+ // Note, this will not drop any forced reset request. If a forced
+ // reset was requested, but we were busy, then when the currently
+ // running reset finishes, a new one will be spun up.
}
}
// Wait for the next chain head event or a previous reset finish
@@ -223,8 +250,26 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
oldHead = head
<-resetBusy
+ // If someone is waiting for a reset to finish, notify them, unless
+ // the forced op is still pending. In that case, wait another round
+ // of resets.
+ if resetWaiter != nil && !resetForced {
+ resetWaiter <- nil
+ resetWaiter = nil
+ }
+
case errc = <-p.quit:
// Termination requested, break out on the next loop round
+
+ case syncc := <-p.sync:
+ // Transaction pool is running inside a simulator, and we are about
+ // to create a new block. Request a forced sync operation to ensure
+ // that any running reset operation finishes to make block imports
+ // deterministic. On top of that, run a new reset operation to make
+ // transaction insertions deterministic instead of being stuck in a
+ // queue waiting for a reset.
+ resetForced = true
+ resetWaiter = syncc
}
}
// Notify the closer of termination (no error possible for now)
@@ -308,10 +353,13 @@ func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
// Pending retrieves all currently processable transactions, grouped by origin
// account and sorted by nonce.
-func (p *TxPool) Pending(enforceTips bool) map[common.Address][]*LazyTransaction {
+//
+// The transactions can also be pre-filtered by the dynamic fee components to
+// reduce allocations and load on downstream subsystems.
+func (p *TxPool) Pending(filter PendingFilter) map[common.Address][]*LazyTransaction {
txs := make(map[common.Address][]*LazyTransaction)
for _, subpool := range p.subpools {
- for addr, set := range subpool.Pending(enforceTips) {
+ for addr, set := range subpool.Pending(filter) {
txs[addr] = set
}
}
@@ -415,3 +463,20 @@ func (p *TxPool) Status(hash common.Hash) TxStatus {
}
return TxStatusUnknown
}
+
+// Sync is a helper method for unit tests or simulator runs where the chain events
+// are arriving in quick succession, without any time in between them to run the
+// internal background reset operations. This method will run an explicit reset
+// operation to ensure the pool stabilises, thus avoiding flakey behavior.
+//
+// Note, do not use this in production / live code. In live code, the pool is
+// meant to reset on a separate thread to avoid DoS vectors.
+func (p *TxPool) Sync() error {
+ sync := make(chan error)
+ select {
+ case p.sync <- sync:
+ return <-sync
+ case <-p.term:
+ return errors.New("pool already terminated")
+ }
+}
diff --git a/core/txpool/validation.go b/core/txpool/validation.go
index faace9cf8a..d2273c24bc 100644
--- a/core/txpool/validation.go
+++ b/core/txpool/validation.go
@@ -30,6 +30,12 @@ import (
"github.com/ethereum/go-ethereum/params"
)
+var (
+ // blobTxMinBlobGasPrice is the big.Int version of the configured protocol
+ // parameter to avoid constucting a new big integer for every transaction.
+ blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
+)
+
// ValidationOptions define certain differences between transaction validation
// across the different pools without having to duplicate those checks.
type ValidationOptions struct {
@@ -103,15 +109,17 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
return err
}
if tx.Gas() < intrGas {
- return fmt.Errorf("%w: needed %v, allowed %v", core.ErrIntrinsicGas, intrGas, tx.Gas())
+ return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), intrGas)
}
- // Ensure the gasprice is high enough to cover the requirement of the calling
- // pool and/or block producer
+ // Ensure the gasprice is high enough to cover the requirement of the calling pool
if tx.GasTipCapIntCmp(opts.MinTip) < 0 {
- return fmt.Errorf("%w: tip needed %v, tip permitted %v", ErrUnderpriced, opts.MinTip, tx.GasTipCap())
+ return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrUnderpriced, tx.GasTipCap(), opts.MinTip)
}
- // Ensure blob transactions have valid commitments
if tx.Type() == types.BlobTxType {
+ // Ensure the blob fee cap satisfies the minimum blob gas price
+ if tx.BlobGasFeeCapIntCmp(blobTxMinBlobGasPrice) < 0 {
+ return fmt.Errorf("%w: blob fee cap %v, minimum needed %v", ErrUnderpriced, tx.BlobGasFeeCap(), blobTxMinBlobGasPrice)
+ }
sidecar := tx.BlobTxSidecar()
if sidecar == nil {
return fmt.Errorf("missing sidecar in blob transaction")
@@ -125,6 +133,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
if len(hashes) > params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob {
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)
}
+ // Ensure commitments, proofs and hashes are valid
if err := validateBlobSidecar(hashes, sidecar); err != nil {
return err
}
@@ -145,17 +154,10 @@ func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) err
// Blob quantities match up, validate that the provers match with the
// transaction hash before getting to the cryptography
hasher := sha256.New()
- for i, want := range hashes {
- hasher.Write(sidecar.Commitments[i][:])
- hash := hasher.Sum(nil)
- hasher.Reset()
-
- var vhash common.Hash
- vhash[0] = params.BlobTxHashVersion
- copy(vhash[1:], hash[1:])
-
- if vhash != want {
- return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, vhash, want)
+ for i, vhash := range hashes {
+ computed := kzg4844.CalcBlobHashV1(hasher, &sidecar.Commitments[i])
+ if vhash != computed {
+ return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, computed, vhash)
}
}
// Blob commitments match with the hashes in the transaction, verify the
@@ -218,7 +220,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
}
// Ensure the transactor has enough funds to cover the transaction costs
var (
- balance = opts.State.GetBalance(from)
+ balance = opts.State.GetBalance(from).ToBig()
cost = tx.Cost()
)
if balance.Cmp(cost) < 0 {
diff --git a/core/types/account.go b/core/types/account.go
new file mode 100644
index 0000000000..bb0f4ca02e
--- /dev/null
+++ b/core/types/account.go
@@ -0,0 +1,87 @@
+// Copyright 2024 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 types
+
+import (
+ "bytes"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/common/math"
+)
+
+//go:generate go run github.com/fjl/gencodec -type Account -field-override accountMarshaling -out gen_account.go
+
+// Account represents an Ethereum account and its attached data.
+// This type is used to specify accounts in the genesis block state, and
+// is also useful for JSON encoding/decoding of accounts.
+type Account struct {
+ Code []byte `json:"code,omitempty"`
+ Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
+ Balance *big.Int `json:"balance" gencodec:"required"`
+ Nonce uint64 `json:"nonce,omitempty"`
+
+ // used in tests
+ PrivateKey []byte `json:"secretKey,omitempty"`
+}
+
+type accountMarshaling struct {
+ Code hexutil.Bytes
+ Balance *math.HexOrDecimal256
+ Nonce math.HexOrDecimal64
+ Storage map[storageJSON]storageJSON
+ PrivateKey hexutil.Bytes
+}
+
+// storageJSON represents a 256 bit byte array, but allows less than 256 bits when
+// unmarshaling from hex.
+type storageJSON common.Hash
+
+func (h *storageJSON) UnmarshalText(text []byte) error {
+ text = bytes.TrimPrefix(text, []byte("0x"))
+ if len(text) > 64 {
+ return fmt.Errorf("too many hex characters in storage key/value %q", text)
+ }
+ offset := len(h) - len(text)/2 // pad on the left
+ if _, err := hex.Decode(h[offset:], text); err != nil {
+ return fmt.Errorf("invalid hex storage key/value %q", text)
+ }
+ return nil
+}
+
+func (h storageJSON) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(h[:]).MarshalText()
+}
+
+// GenesisAlloc specifies the initial state of a genesis block.
+type GenesisAlloc map[common.Address]Account
+
+func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
+ m := make(map[common.UnprefixedAddress]Account)
+ if err := json.Unmarshal(data, &m); err != nil {
+ return err
+ }
+ *ga = make(GenesisAlloc)
+ for addr, a := range m {
+ (*ga)[common.Address(addr)] = a
+ }
+ return nil
+}
diff --git a/core/gen_genesis_account.go b/core/types/gen_account.go
similarity index 61%
rename from core/gen_genesis_account.go
rename to core/types/gen_account.go
index d21280e257..8dda4f06ba 100644
--- a/core/gen_genesis_account.go
+++ b/core/types/gen_account.go
@@ -1,6 +1,6 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-package core
+package types
import (
"encoding/json"
@@ -12,72 +12,66 @@ import (
"github.com/ethereum/go-ethereum/common/math"
)
-var _ = (*genesisAccountMarshaling)(nil)
+var _ = (*accountMarshaling)(nil)
// MarshalJSON marshals as JSON.
-func (g GenesisAccount) MarshalJSON() ([]byte, error) {
- type GenesisAccount struct {
+func (a Account) MarshalJSON() ([]byte, error) {
+ type Account struct {
Code hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey hexutil.Bytes `json:"secretKey,omitempty"`
}
-
- var enc GenesisAccount
-
- enc.Code = g.Code
- if g.Storage != nil {
- enc.Storage = make(map[storageJSON]storageJSON, len(g.Storage))
- for k, v := range g.Storage {
+ var enc Account
+ enc.Code = a.Code
+ if a.Storage != nil {
+ enc.Storage = make(map[storageJSON]storageJSON, len(a.Storage))
+ for k, v := range a.Storage {
enc.Storage[storageJSON(k)] = storageJSON(v)
}
}
-
- enc.Balance = (*math.HexOrDecimal256)(g.Balance)
- enc.Nonce = math.HexOrDecimal64(g.Nonce)
- enc.PrivateKey = g.PrivateKey
-
+ enc.Balance = (*math.HexOrDecimal256)(a.Balance)
+ enc.Nonce = math.HexOrDecimal64(a.Nonce)
+ enc.PrivateKey = a.PrivateKey
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
-func (g *GenesisAccount) UnmarshalJSON(input []byte) error {
- type GenesisAccount struct {
+func (a *Account) UnmarshalJSON(input []byte) error {
+ type Account struct {
Code *hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"`
}
-
- var dec GenesisAccount
+ var dec Account
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Code != nil {
- g.Code = *dec.Code
+ a.Code = *dec.Code
}
if dec.Storage != nil {
- g.Storage = make(map[common.Hash]common.Hash, len(dec.Storage))
+ a.Storage = make(map[common.Hash]common.Hash, len(dec.Storage))
for k, v := range dec.Storage {
- g.Storage[common.Hash(k)] = common.Hash(v)
+ a.Storage[common.Hash(k)] = common.Hash(v)
}
}
if dec.Balance == nil {
- return errors.New("missing required field 'balance' for GenesisAccount")
+ return errors.New("missing required field 'balance' for Account")
}
-
- g.Balance = (*big.Int)(dec.Balance)
+ a.Balance = (*big.Int)(dec.Balance)
if dec.Nonce != nil {
- g.Nonce = uint64(*dec.Nonce)
+ a.Nonce = uint64(*dec.Nonce)
}
if dec.PrivateKey != nil {
- g.PrivateKey = *dec.PrivateKey
+ a.PrivateKey = *dec.PrivateKey
}
return nil
diff --git a/core/types/gen_account_rlp.go b/core/types/gen_account_rlp.go
index 3fb36f4038..8b424493af 100644
--- a/core/types/gen_account_rlp.go
+++ b/core/types/gen_account_rlp.go
@@ -12,10 +12,7 @@ func (obj *StateAccount) EncodeRLP(_w io.Writer) error {
if obj.Balance == nil {
w.Write(rlp.EmptyString)
} else {
- if obj.Balance.Sign() == -1 {
- return rlp.ErrNegativeBigInt
- }
- w.WriteBigInt(obj.Balance)
+ w.WriteUint256(obj.Balance)
}
w.WriteBytes(obj.Root[:])
w.WriteBytes(obj.CodeHash)
diff --git a/core/types/hashing_test.go b/core/types/hashing_test.go
index 3d2596ec5e..e8de5105fa 100644
--- a/core/types/hashing_test.go
+++ b/core/types/hashing_test.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func TestDeriveSha(t *testing.T) {
@@ -40,7 +41,7 @@ func TestDeriveSha(t *testing.T) {
}
for len(txs) < 1000 {
- exp := types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
+ exp := types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
got := types.DeriveSha(txs, trie.NewStackTrie(nil))
if !bytes.Equal(got[:], exp[:]) {
@@ -97,7 +98,7 @@ func BenchmarkDeriveSha200(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- exp = types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
+ exp = types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
}
})
@@ -120,7 +121,7 @@ func TestFuzzDeriveSha(t *testing.T) {
rndSeed := mrand.Int()
for i := 0; i < 10; i++ {
seed := rndSeed + i
- exp := types.DeriveSha(newDummy(i), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
+ exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil))
if !bytes.Equal(got[:], exp[:]) {
@@ -150,7 +151,7 @@ func TestDerivableList(t *testing.T) {
},
}
for i, tc := range tcs[1:] {
- exp := types.DeriveSha(flatList(tc), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
+ exp := types.DeriveSha(flatList(tc), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
got := types.DeriveSha(flatList(tc), trie.NewStackTrie(nil))
if !bytes.Equal(got[:], exp[:]) {
diff --git a/core/types/state_account.go b/core/types/state_account.go
index ad07ca3f3a..52ef843b35 100644
--- a/core/types/state_account.go
+++ b/core/types/state_account.go
@@ -18,10 +18,10 @@ package types
import (
"bytes"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/holiman/uint256"
)
//go:generate go run ../../rlp/rlpgen -type StateAccount -out gen_account_rlp.go
@@ -30,7 +30,7 @@ import (
// These objects are stored in the main account trie.
type StateAccount struct {
Nonce uint64
- Balance *big.Int
+ Balance *uint256.Int
Root common.Hash // merkle root of the storage trie
CodeHash []byte
}
@@ -38,7 +38,7 @@ type StateAccount struct {
// NewEmptyStateAccount constructs an empty state account.
func NewEmptyStateAccount() *StateAccount {
return &StateAccount{
- Balance: new(big.Int),
+ Balance: new(uint256.Int),
Root: EmptyRootHash,
CodeHash: EmptyCodeHash.Bytes(),
}
@@ -46,9 +46,9 @@ func NewEmptyStateAccount() *StateAccount {
// Copy returns a deep-copied state account object.
func (acct *StateAccount) Copy() *StateAccount {
- var balance *big.Int
+ var balance *uint256.Int
if acct.Balance != nil {
- balance = new(big.Int).Set(acct.Balance)
+ balance = new(uint256.Int).Set(acct.Balance)
}
return &StateAccount{
Nonce: acct.Nonce,
@@ -63,7 +63,7 @@ func (acct *StateAccount) Copy() *StateAccount {
// or slim format which replaces the empty root and code hash as nil byte slice.
type SlimAccount struct {
Nonce uint64
- Balance *big.Int
+ Balance *uint256.Int
Root []byte // Nil if root equals to types.EmptyRootHash
CodeHash []byte // Nil if hash equals to types.EmptyCodeHash
}
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 22d969e4cb..9610393337 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -19,6 +19,7 @@ package types
import (
"bytes"
"errors"
+ "fmt"
"io"
"math/big"
"sync/atomic"
@@ -334,6 +335,7 @@ func (tx *Transaction) Cost() *big.Int {
// RawSignatureValues returns the V, R, S signature values of the transaction.
// The return values should not be modified by the caller.
+// The return values may be nil or zero, if the transaction is unsigned.
func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) {
return tx.inner.rawSignatureValues()
}
@@ -522,6 +524,9 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
if err != nil {
return nil, err
}
+ if r == nil || s == nil || v == nil {
+ return nil, fmt.Errorf("%w: r: %s, s: %s, v: %s", ErrInvalidSig, r, s, v)
+ }
cpy := tx.inner.copy()
cpy.setSignatureValues(signer.ChainID(), v, r, s)
return &Transaction{inner: cpy, time: tx.time}, nil
diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go
index 08ce80b07c..4d5b2bcdd4 100644
--- a/core/types/transaction_marshalling.go
+++ b/core/types/transaction_marshalling.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/holiman/uint256"
)
@@ -47,6 +48,11 @@ type txJSON struct {
S *hexutil.Big `json:"s"`
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
+ // Blob transaction sidecar encoding:
+ Blobs []kzg4844.Blob `json:"blobs,omitempty"`
+ Commitments []kzg4844.Commitment `json:"commitments,omitempty"`
+ Proofs []kzg4844.Proof `json:"proofs,omitempty"`
+
// Only used for encoding:
Hash common.Hash `json:"hash"`
}
@@ -142,6 +148,11 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
enc.S = (*hexutil.Big)(itx.S.ToBig())
yparity := itx.V.Uint64()
enc.YParity = (*hexutil.Uint64)(&yparity)
+ if sidecar := itx.Sidecar; sidecar != nil {
+ enc.Blobs = itx.Sidecar.Blobs
+ enc.Commitments = itx.Sidecar.Commitments
+ enc.Proofs = itx.Sidecar.Proofs
+ }
}
return json.Marshal(&enc)
}
diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go
index 4cce32f208..7cab59f677 100644
--- a/core/types/transaction_signing_test.go
+++ b/core/types/transaction_signing_test.go
@@ -18,11 +18,13 @@ package types
import (
"errors"
+ "fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -143,3 +145,53 @@ func TestChainId(t *testing.T) {
t.Error("expected no error")
}
}
+
+type nilSigner struct {
+ v, r, s *big.Int
+ Signer
+}
+
+func (ns *nilSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
+ return ns.v, ns.r, ns.s, nil
+}
+
+// TestNilSigner ensures a faulty Signer implementation does not result in nil signature values or panics.
+func TestNilSigner(t *testing.T) {
+ key, _ := crypto.GenerateKey()
+ innerSigner := LatestSignerForChainID(big.NewInt(1))
+ for i, signer := range []Signer{
+ &nilSigner{v: nil, r: nil, s: nil, Signer: innerSigner},
+ &nilSigner{v: big.NewInt(1), r: big.NewInt(1), s: nil, Signer: innerSigner},
+ &nilSigner{v: big.NewInt(1), r: nil, s: big.NewInt(1), Signer: innerSigner},
+ &nilSigner{v: nil, r: big.NewInt(1), s: big.NewInt(1), Signer: innerSigner},
+ } {
+ t.Run(fmt.Sprintf("signer_%d", i), func(t *testing.T) {
+ t.Run("legacy", func(t *testing.T) {
+ legacyTx := createTestLegacyTxInner()
+ _, err := SignNewTx(key, signer, legacyTx)
+ if !errors.Is(err, ErrInvalidSig) {
+ t.Fatal("expected signature values error, no nil result or panic")
+ }
+ })
+ // test Blob tx specifically, since the signature value types changed
+ t.Run("blobtx", func(t *testing.T) {
+ blobtx := createEmptyBlobTxInner(false)
+ _, err := SignNewTx(key, signer, blobtx)
+ if !errors.Is(err, ErrInvalidSig) {
+ t.Fatal("expected signature values error, no nil result or panic")
+ }
+ })
+ })
+ }
+}
+
+func createTestLegacyTxInner() *LegacyTx {
+ return &LegacyTx{
+ Nonce: uint64(0),
+ To: nil,
+ Value: big.NewInt(0),
+ Gas: params.TxGas,
+ GasPrice: big.NewInt(params.GWei),
+ Data: nil,
+ }
+}
diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go
index da4a9b72f1..25a85695ef 100644
--- a/core/types/tx_blob.go
+++ b/core/types/tx_blob.go
@@ -43,7 +43,7 @@ type BlobTx struct {
BlobHashes []common.Hash
// A blob transaction can optionally contain blobs. This field must be set when BlobTx
- // is used to create a transaction for sigining.
+ // is used to create a transaction for signing.
Sidecar *BlobTxSidecar `rlp:"-"`
// Signature values
@@ -61,9 +61,10 @@ type BlobTxSidecar struct {
// BlobHashes computes the blob hashes of the given blobs.
func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
+ hasher := sha256.New()
h := make([]common.Hash, len(sc.Commitments))
for i := range sc.Blobs {
- h[i] = blobHash(&sc.Commitments[i])
+ h[i] = kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i])
}
return h
}
@@ -235,12 +236,3 @@ func (tx *BlobTx) decode(input []byte) error {
}
return nil
}
-
-func blobHash(commit *kzg4844.Commitment) common.Hash {
- hasher := sha256.New()
- hasher.Write(commit[:])
- var vhash common.Hash
- hasher.Sum(vhash[:0])
- vhash[0] = params.BlobTxHashVersion
- return vhash
-}
diff --git a/core/types/tx_blob_test.go b/core/types/tx_blob_test.go
index 44ac48cc6f..25d09e31ce 100644
--- a/core/types/tx_blob_test.go
+++ b/core/types/tx_blob_test.go
@@ -65,6 +65,12 @@ var (
)
func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
+ blobtx := createEmptyBlobTxInner(withSidecar)
+ signer := NewCancunSigner(blobtx.ChainID.ToBig())
+ return MustSignNewTx(key, signer, blobtx)
+}
+
+func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
sidecar := &BlobTxSidecar{
Blobs: []kzg4844.Blob{emptyBlob},
Commitments: []kzg4844.Commitment{emptyBlobCommit},
@@ -85,6 +91,5 @@ func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
if withSidecar {
blobtx.Sidecar = sidecar
}
- signer := NewCancunSigner(blobtx.ChainID.ToBig())
- return MustSignNewTx(key, signer, blobtx)
+ return blobtx
}
diff --git a/core/vm/contract.go b/core/vm/contract.go
index 89354e3d1b..1b372ae10d 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -17,8 +17,6 @@
package vm
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)
@@ -59,11 +57,11 @@ type Contract struct {
Input []byte
Gas uint64
- value *big.Int
+ value *uint256.Int
}
// NewContract returns a new contract environment for the execution of EVM.
-func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
+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 {
@@ -178,7 +176,7 @@ func (c *Contract) Address() common.Address {
}
// Value returns the contract's value (sent to it from it's caller)
-func (c *Contract) Value() *big.Int {
+func (c *Contract) Value() *uint256.Int {
return c.value
}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 382c1ab405..53883d0e68 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -274,7 +274,6 @@ type bigModExp struct {
}
var (
- big0 = big.NewInt(0)
big1 = big.NewInt(1)
big3 = big.NewInt(3)
big4 = big.NewInt(4)
diff --git a/core/vm/eips.go b/core/vm/eips.go
index ca46f192d7..2751963cb5 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -89,7 +89,7 @@ func enable1884(jt *JumpTable) {
}
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- balance, _ := uint256.FromBig(interpreter.evm.StateDB.GetBalance(scope.Contract.Address()))
+ balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
scope.Stack.push(balance)
return nil, nil
diff --git a/core/vm/evm.go b/core/vm/evm.go
index e6d1648901..bc28ec3783 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -30,9 +30,9 @@ import (
type (
// CanTransferFunc is the signature of a transfer guard function
- CanTransferFunc func(StateDB, common.Address, *big.Int) bool
+ CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool
// TransferFunc is the signature of a transfer function
- TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
+ TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int)
// GetHashFunc returns the n'th block hash in the blockchain
// and is used by the BLOCKHASH EVM op code.
GetHashFunc func(uint64) common.Hash
@@ -181,13 +181,13 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
// parameters. It also handles any necessary value transfer required and takes
// 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 *big.Int, interruptCtx context.Context) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int, interruptCtx context.Context) (ret []byte, leftOverGas uint64, err error) {
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
}
// Fail if we're trying to transfer more than the available balance
- if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
+ if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
return nil, gas, ErrInsufficientBalance
}
@@ -196,14 +196,14 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
debug := evm.Config.Tracer != nil
if !evm.StateDB.Exist(addr) {
- if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
+ if !isPrecompile && evm.chainRules.IsEIP158 && value.IsZero() {
// Calling a non existing account, don't do anything, but ping the tracer
if debug {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig())
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
} else {
- evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value.ToBig())
evm.Config.Tracer.CaptureExit(ret, 0, nil)
}
}
@@ -219,13 +219,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// Capture the tracer start/end events in debug mode
if debug {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig())
defer func(startGas uint64) { // Lazy evaluation of the parameters
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
}(gas)
} else {
// Handle tracer events for entering and exiting a call frame
- evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -274,7 +274,7 @@ 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 *big.Int) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
@@ -291,7 +291,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
- evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -340,7 +340,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// that caller is something other than a Contract.
parent := caller.(*Contract)
// DELEGATECALL inherits value from parent call
- evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value)
+ evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -389,7 +389,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
// but is the correct thing to do and matters on other networks, in tests, and potential
// future scenarios
- evm.StateDB.AddBalance(addr, big0)
+ evm.StateDB.AddBalance(addr, new(uint256.Int))
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
@@ -408,7 +408,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
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(big.Int), gas)
+ contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
// 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
@@ -442,7 +442,7 @@ func (c *codeAndHash) Hash() common.Hash {
}
// create creates a new contract using code as deployment code.
-func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
+func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
@@ -486,9 +486,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.Config.Tracer != nil {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value.ToBig())
} else {
- evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
+ evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig())
}
}
@@ -540,7 +540,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
// Create creates a new contract using code as deployment code.
-func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+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)
}
@@ -549,7 +549,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
//
// 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 *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+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())
diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go
index 53827f268c..990e66878d 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/gas_table_test.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
func TestMemoryGasCost(t *testing.T) {
@@ -92,12 +93,12 @@ func TestEIP2200(t *testing.T) {
statedb.Finalise(true) // Push the state into the "original" slot
vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
- _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int), nil)
+ _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int), nil)
if err != tt.failure {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
}
@@ -148,8 +149,8 @@ func TestCreateGas(t *testing.T) {
statedb.Finalise(true)
vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
BlockNumber: big.NewInt(0),
}
config := Config{}
@@ -161,7 +162,7 @@ func TestCreateGas(t *testing.T) {
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas)
- ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(big.Int), nil)
+ ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int), nil)
if err != nil {
return false
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index acd9a8c780..6fee3014f8 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -17,6 +17,8 @@
package vm
import (
+ "math"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -289,7 +291,8 @@ func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.peek()
address := common.Address(slot.Bytes20())
- slot.SetFromBig(interpreter.evm.StateDB.GetBalance(address))
+
+ slot.Set(interpreter.evm.StateDB.GetBalance(address))
return nil, nil
}
@@ -305,8 +308,7 @@ func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
}
func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- v, _ := uint256.FromBig(scope.Contract.value)
- scope.Stack.push(v)
+ scope.Stack.push(scope.Contract.value)
return nil, nil
}
@@ -386,9 +388,7 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
}
func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- l := new(uint256.Int)
- l.SetUint64(uint64(len(scope.Contract.Code)))
- scope.Stack.push(l)
+ scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code))))
return nil, nil
}
@@ -402,7 +402,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow {
- uint64CodeOffset = 0xffffffffffffffff
+ uint64CodeOffset = math.MaxUint64
}
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
@@ -422,7 +422,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow {
- uint64CodeOffset = 0xffffffffffffffff
+ uint64CodeOffset = math.MaxUint64
}
addr := common.Address(a.Bytes20())
@@ -660,13 +660,8 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
stackvalue := size
scope.Contract.UseGas(gas)
- //TODO: use uint256.Int instead of converting with toBig()
- var bigVal = big0
- if !value.IsZero() {
- bigVal = value.ToBig()
- }
- res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, bigVal)
+ res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, 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
@@ -709,14 +704,9 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
scope.Contract.UseGas(gas)
// reuse size int for stackvalue
stackvalue := size
- //TODO: use uint256.Int instead of converting with toBig()
- bigEndowment := big0
- if !endowment.IsZero() {
- bigEndowment = endowment.ToBig()
- }
res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas,
- bigEndowment, &salt)
+ &endowment, &salt)
// Push item on the stack based on the returned error.
if suberr != nil {
stackvalue.Clear()
@@ -753,16 +743,11 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
return nil, ErrWriteProtection
}
- var bigVal = big0
- //TODO: use uint256.Int instead of converting with toBig()
- // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls),
- // but it would make more sense to extend the usage of uint256.Int
if !value.IsZero() {
gas += params.CallStipend
- bigVal = value.ToBig()
}
- ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, bigVal, nil)
+ ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value, nil)
if err != nil {
temp.Clear()
@@ -795,15 +780,11 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
// Get arguments from the memory.
args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
- //TODO: use uint256.Int instead of converting with toBig()
- var bigVal = big0
-
if !value.IsZero() {
gas += params.CallStipend
- bigVal = value.ToBig()
}
- ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, bigVal)
+ ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, &value)
if err != nil {
temp.Clear()
} else {
@@ -921,7 +902,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
- tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
tracer.CaptureExit([]byte{}, 0, nil)
}
return nil, errStopToken
@@ -937,7 +918,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
- tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
tracer.CaptureExit([]byte{}, 0, nil)
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index bdd10e7f91..a44ee2e72a 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -622,7 +622,7 @@ func TestOpTstore(t *testing.T) {
caller = common.Address{}
to = common.Address{1}
contractRef = contractRef{caller}
- contract = NewContract(contractRef, AccountRef(to), new(big.Int), 0)
+ contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
scopeContext = ScopeContext{mem, stack, contract}
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
)
diff --git a/core/vm/interface.go b/core/vm/interface.go
index b3b0990c27..a018daaf50 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -22,15 +22,16 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// StateDB is an EVM database for full state querying.
type StateDB interface {
CreateAccount(common.Address)
- SubBalance(common.Address, *big.Int)
- AddBalance(common.Address, *big.Int)
- GetBalance(common.Address) *big.Int
+ SubBalance(common.Address, *uint256.Int)
+ AddBalance(common.Address, *uint256.Int)
+ GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go
index 245ebcb7de..76d0e46e90 100644
--- a/core/vm/interpreter_test.go
+++ b/core/vm/interpreter_test.go
@@ -17,7 +17,6 @@
package vm
import (
- "math/big"
"testing"
"time"
@@ -27,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var loopInterruptTests = []string{
@@ -39,7 +39,7 @@ var loopInterruptTests = []string{
func TestLoopInterrupt(t *testing.T) {
address := common.BytesToAddress([]byte("contract"))
vmctx := BlockContext{
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
for i, tt := range loopInterruptTests {
@@ -54,7 +54,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(big.Int), nil)
+ _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int), nil)
errChannel <- err
}(evm)
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index a65ba0a3d5..0552be2169 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -129,7 +129,7 @@ func newLondonInstructionSet() JumpTable {
// constantinople, istanbul, petersburg and berlin instructions.
func newBerlinInstructionSet() JumpTable {
instructionSet := newIstanbulInstructionSet()
- enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
+ enable2929(&instructionSet) // Gas cost increases for state access opcodes https://eips.ethereum.org/EIPS/eip-2929
return validate(instructionSet)
}
diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go
index 3050af22fb..7e0d768830 100644
--- a/core/vm/operations_acl.go
+++ b/core/vm/operations_acl.go
@@ -201,7 +201,11 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc) gasFunc {
// also become correctly reported to tracers.
contract.Gas += coldCost
- return gas + coldCost, nil
+ var overflow bool
+ if gas, overflow = math.SafeAdd(gas, coldCost); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
}
}
@@ -211,7 +215,7 @@ var (
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall)
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode)
gasSelfdestructEIP2929 = makeSelfdestructGasFn(true)
- // gasSelfdestructEIP3529 implements the changes in EIP-2539 (no refunds)
+ // gasSelfdestructEIP3529 implements the changes in EIP-3529 (no refunds)
gasSelfdestructEIP3529 = makeSelfdestructGasFn(false)
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
@@ -228,12 +232,12 @@ var (
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200)
- // gasSStoreEIP2539 implements gas cost for SSTORE according to EIP-2539
+ // gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
)
-// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539
+// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 0f6d2c5c66..24e6db327a 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// Config is a basic type specifying certain configuration flags for running
@@ -143,7 +144,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
common.BytesToAddress([]byte("contract")),
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
nil,
)
@@ -176,7 +177,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
sender,
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
)
return code, address, leftOverGas, err
@@ -192,7 +193,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
var (
vmenv = NewEnv(cfg)
- sender = cfg.State.GetOrNewStateObject(cfg.Origin)
+ sender = vm.AccountRef(cfg.Origin)
statedb = cfg.State
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
)
@@ -207,7 +208,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
address,
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
nil,
)
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index 2a7b5eba68..bcc6de897a 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -38,6 +38,7 @@ import (
// force-load js tracers to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
+ "github.com/holiman/uint256"
)
func TestDefaults(t *testing.T) {
@@ -385,14 +386,14 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
cfg.State.SetCode(destination, code)
// nolint: errcheck
- vmenv.Call(sender, destination, nil, gas, cfg.Value, nil)
+ vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value), nil)
b.Run(name, func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// nolint: errcheck
- vmenv.Call(sender, destination, nil, gas, cfg.Value, nil)
+ vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value), nil)
}
})
}
diff --git a/crypto/bn256/google/bn256.go b/crypto/bn256/google/bn256.go
index dc1c08b41a..91cb09736c 100644
--- a/crypto/bn256/google/bn256.go
+++ b/crypto/bn256/google/bn256.go
@@ -181,7 +181,7 @@ type G2 struct {
p *twistPoint
}
-// RandomG1 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r.
+// RandomG2 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r.
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
var k *big.Int
diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go
index 5969d1c2ce..52124df674 100644
--- a/crypto/kzg4844/kzg4844.go
+++ b/crypto/kzg4844/kzg4844.go
@@ -20,21 +20,61 @@ package kzg4844
import (
"embed"
"errors"
+ "hash"
+ "reflect"
"sync/atomic"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
)
//go:embed trusted_setup.json
var content embed.FS
+var (
+ blobT = reflect.TypeOf(Blob{})
+ commitmentT = reflect.TypeOf(Commitment{})
+ proofT = reflect.TypeOf(Proof{})
+)
+
// Blob represents a 4844 data blob.
type Blob [131072]byte
+// UnmarshalJSON parses a blob in hex syntax.
+func (b *Blob) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(blobT, input, b[:])
+}
+
+// MarshalText returns the hex representation of b.
+func (b Blob) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(b[:]).MarshalText()
+}
+
// Commitment is a serialized commitment to a polynomial.
type Commitment [48]byte
+// UnmarshalJSON parses a commitment in hex syntax.
+func (c *Commitment) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(commitmentT, input, c[:])
+}
+
+// MarshalText returns the hex representation of c.
+func (c Commitment) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(c[:]).MarshalText()
+}
+
// Proof is a serialized commitment to the quotient polynomial.
type Proof [48]byte
+// UnmarshalJSON parses a proof in hex syntax.
+func (p *Proof) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(proofT, input, p[:])
+}
+
+// MarshalText returns the hex representation of p.
+func (p Proof) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(p[:]).MarshalText()
+}
+
// Point is a BLS field element.
type Point [32]byte
@@ -108,3 +148,21 @@ func VerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
}
return gokzgVerifyBlobProof(blob, commitment, proof)
}
+
+// CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment.
+// The given hasher must be a sha256 hash instance, otherwise the result will be invalid!
+func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) {
+ if hasher.Size() != 32 {
+ panic("wrong hash size")
+ }
+ hasher.Reset()
+ hasher.Write(commit[:])
+ hasher.Sum(vh[:0])
+ vh[0] = 0x01 // version
+ return vh
+}
+
+// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash.
+func IsValidVersionedHash(h []byte) bool {
+ return len(h) == 32 && h[0] == 0x01
+}
diff --git a/docs/postmortems/2021-08-22-split-postmortem.md b/docs/postmortems/2021-08-22-split-postmortem.md
index 962aa51f64..0986f00b65 100644
--- a/docs/postmortems/2021-08-22-split-postmortem.md
+++ b/docs/postmortems/2021-08-22-split-postmortem.md
@@ -87,7 +87,7 @@ The blocks on the 'bad' chain were investigated, and Tim Beiko reached out to th
### Disclosure decision
-The geth-team have an official policy regarding [vulnerability disclosure](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities).
+The geth-team have an official policy regarding [vulnerability disclosure](https://geth.ethereum.org/docs/developers/geth-developer/disclosures).
> The primary goal for the Geth team is the health of the Ethereum network as a whole, and the decision whether or not to publish details about a serious vulnerability boils down to minimizing the risk and/or impact of discovery and exploitation.
diff --git a/eth/api_backend.go b/eth/api_backend.go
index c71db480b3..a6ebe3e184 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -296,7 +296,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
} else {
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
}
- return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig)
+ return vm.NewEVM(context, txContext, state, b.ChainConfig(), *vmConfig)
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
@@ -328,7 +328,7 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
}
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
- pending := b.eth.txPool.Pending(false)
+ pending := b.eth.txPool.Pending(txpool.PendingFilter{})
var txs types.Transactions
@@ -347,9 +347,25 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction
return b.eth.txPool.Get(hash)
}
-func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
- return tx, blockHash, blockNumber, index, nil
+// GetTransaction retrieves the lookup along with the transaction itself associate
+// with the given transaction hash.
+//
+// An error will be returned if the transaction is not found, and background
+// indexing for transactions is still in progress. The error is used to indicate the
+// scenario explicitly that the transaction might be reachable shortly.
+//
+// A null will be returned in the transaction is not found and background transaction
+// indexing is already finished. The transaction is not existent from the perspective
+// of node.
+func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash)
+ if err != nil {
+ return false, nil, common.Hash{}, 0, 0, err
+ }
+ if lookup == nil || tx == nil {
+ return false, nil, common.Hash{}, 0, 0, nil
+ }
+ return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
@@ -377,7 +393,12 @@ func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
}
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
- return b.eth.Downloader().Progress()
+ prog := b.eth.Downloader().Progress()
+ if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
}
func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go
index 4ccda71def..0b954845e6 100644
--- a/eth/api_debug_test.go
+++ b/eth/api_debug_test.go
@@ -19,7 +19,6 @@ package eth
import (
"bytes"
"fmt"
- "math/big"
"reflect"
"strings"
"testing"
@@ -30,7 +29,8 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
"golang.org/x/exp/slices"
)
@@ -64,7 +64,7 @@ func TestAccountRange(t *testing.T) {
t.Parallel()
var (
- statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true})
+ statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
sdb, _ = state.New(types.EmptyRootHash, statedb, nil)
addrs = [AccountRangeMaxResults * 2]common.Address{}
m = map[common.Address]bool{}
@@ -74,7 +74,7 @@ func TestAccountRange(t *testing.T) {
hash := common.HexToHash(fmt.Sprintf("%x", i))
addr := common.BytesToAddress(crypto.Keccak256Hash(hash.Bytes()).Bytes())
addrs[i] = addr
- sdb.SetBalance(addrs[i], big.NewInt(1))
+ sdb.SetBalance(addrs[i], uint256.NewInt(1))
if _, ok := m[addr]; ok {
t.Fatalf("bad")
} else {
@@ -162,7 +162,7 @@ func TestStorageRangeAt(t *testing.T) {
// Create a state where account 0x010000... has a few storage entries.
var (
- db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true})
+ db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
sdb, _ = state.New(types.EmptyRootHash, db, nil)
addr = common.Address{0x01}
keys = []common.Hash{ // hashes of Keys of storage
diff --git a/eth/api_miner.go b/eth/api_miner.go
index 2fe296548a..764d0ae5e2 100644
--- a/eth/api_miner.go
+++ b/eth/api_miner.go
@@ -29,7 +29,7 @@ type MinerAPI struct {
e *Ethereum
}
-// NewMinerAPI create a new MinerAPI instance.
+// NewMinerAPI creates a new MinerAPI instance.
func NewMinerAPI(e *Ethereum) *MinerAPI {
return &MinerAPI{e}
}
diff --git a/eth/backend.go b/eth/backend.go
index 627e39d1f0..dcec0f4a4f 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -62,7 +62,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// Config contains the configuration options of the ETH protocol.
@@ -193,7 +193,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
overrides.OverrideVerkle = config.OverrideVerkle
}
- chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, trie.NewDatabase(chainDb, trie.HashDefaults), config.Genesis, &overrides)
+ chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, triedb.NewDatabase(chainDb, triedb.HashDefaults), config.Genesis, &overrides)
if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat {
return nil, genesisErr
}
@@ -273,7 +273,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
legacyPool := legacypool.New(config.TxPool, eth.blockchain)
- eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool})
+ eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool, nil})
if err != nil {
return nil, err
}
diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go
index 923e0ec3bd..bdd14047b1 100644
--- a/eth/catalyst/api.go
+++ b/eth/catalyst/api.go
@@ -31,9 +31,12 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"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"
)
@@ -88,6 +91,7 @@ var caps = []string{
"engine_newPayloadV3",
"engine_getPayloadBodiesByHashV1",
"engine_getPayloadBodiesByRangeV1",
+ "engine_getClientVersionV1",
}
type ConsensusAPI struct {
@@ -173,61 +177,67 @@ func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI {
// and return its payloadID.
func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if payloadAttributes != nil {
- if payloadAttributes.Withdrawals != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
+ if payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals and beacon root not supported in V1"))
}
if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock) {
return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
+ return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false)
}
-// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
-func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
- if payloadAttributes != nil {
- if err := api.verifyPayloadAttributes(payloadAttributes); err != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(err)
+// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload
+// attributes. It supports both PayloadAttributesV1 and PayloadAttributesV2.
+func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) {
+ case forks.Paris:
+ if params.Withdrawals != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals before shanghai"))
+ }
+ case forks.Shanghai:
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals"))
+ }
+ default:
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called with paris and shanghai payloads"))
+ }
+ if params.BeaconRoot != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("unexpected beacon root"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
+ return api.forkchoiceUpdated(update, params, engine.PayloadV2, false)
}
-// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes.
-func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
- if payloadAttributes != nil {
- if err := api.verifyPayloadAttributes(payloadAttributes); err != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(err)
+// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root
+// in the payload attributes. It supports only PayloadAttributesV3.
+func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ // TODO(matt): according to https://github.com/ethereum/execution-apis/pull/498,
+ // payload attributes that are invalid should return error
+ // engine.InvalidPayloadAttributes. Once hive updates this, we should update
+ // on our end.
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals"))
+ }
+ if params.BeaconRoot == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing beacon root"))
+ }
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
+
+ // TODO(matt): the spec requires that fcu is applied when called on a valid
+ // hash, even if params are wrong. To do this we need to split up
+ // forkchoiceUpdate into a function that only updates the head and then a
+ // function that kicks off block construction.
+
+ return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
}
-func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error {
- c := api.eth.BlockChain().Config()
-
- // Verify withdrawals attribute for Shanghai.
- if err := checkAttribute(c.IsShanghai, attr.Withdrawals != nil, c.LondonBlock, attr.Timestamp); err != nil {
- return fmt.Errorf("invalid withdrawals: %w", err)
- }
- // Verify beacon root attribute for Cancun.
- if err := checkAttribute(c.IsCancun, attr.BeaconRoot != nil, c.LondonBlock, attr.Timestamp); err != nil {
- return fmt.Errorf("invalid parent beacon block root: %w", err)
- }
- return nil
-}
-
-func checkAttribute(active func(*big.Int) bool, exists bool, block *big.Int, time uint64) error {
- if active(block) && !exists {
- return errors.New("fork active, missing expected attribute")
- }
- if !active(block) && exists {
- return errors.New("fork inactive, unexpected attribute set")
- }
- return nil
-}
-
-func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) {
api.forkchoiceLock.Lock()
defer api.forkchoiceLock.Unlock()
@@ -334,7 +344,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if merger := api.eth.Merger(); !merger.PoSFinalized() {
merger.FinalizePoS()
}
- // If the finalized block is not in our canonical tree, somethings wrong
+ // If the finalized block is not in our canonical tree, something is wrong
finalBlock := api.eth.BlockChain().GetBlockByHash(update.FinalizedBlockHash)
if finalBlock == nil {
log.Warn("Final block not available in database", "hash", update.FinalizedBlockHash)
@@ -346,7 +356,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
// Set the finalized block
api.eth.BlockChain().SetFinalized(finalBlock.Header())
}
- // Check if the safe block hash is in our canonical tree, if not somethings wrong
+ // Check if the safe block hash is in our canonical tree, if not something is wrong
if update.SafeBlockHash != (common.Hash{}) {
safeBlock := api.eth.BlockChain().GetBlockByHash(update.SafeBlockHash)
if safeBlock == nil {
@@ -371,6 +381,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
Random: payloadAttributes.Random,
Withdrawals: payloadAttributes.Withdrawals,
BeaconRoot: payloadAttributes.BeaconRoot,
+ Version: payloadVersion,
}
id := args.Id()
// If we already are busy generating this work, then we do not need
@@ -378,6 +389,19 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if api.localBlocks.has(id) {
return valid(&id), nil
}
+ // If the beacon chain is ran by a simulator, then transaction insertion,
+ // block insertion and block production will happen without any timing
+ // delay between them. This will cause flaky simulator executions due to
+ // the transaction pool running its internal reset operation on a back-
+ // ground thread. To avoid the racey behavior - in simulator mode - the
+ // pool will be explicitly blocked on its reset before continuing to the
+ // block production below.
+ if simulatorMode {
+ if err := api.eth.TxPool().Sync(); err != nil {
+ log.Error("Failed to sync transaction pool", "err", err)
+ return valid(nil), engine.InvalidPayloadAttributes.With(err)
+ }
+ }
payload, err := api.eth.Miner().BuildPayload(args)
if err != nil {
log.Error("Failed to build payload", "err", err)
@@ -421,6 +445,9 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit
// GetPayloadV1 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) {
+ if !payloadID.Is(engine.PayloadV1) {
+ return nil, engine.UnsupportedFork
+ }
data, err := api.getPayload(payloadID, false)
if err != nil {
return nil, err
@@ -430,11 +457,17 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
// GetPayloadV2 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) {
+ return nil, engine.UnsupportedFork
+ }
return api.getPayload(payloadID, false)
}
// GetPayloadV3 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV3) {
+ return nil, engine.UnsupportedFork
+ }
return api.getPayload(payloadID, false)
}
@@ -461,9 +494,13 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
if params.Withdrawals == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
}
- } else if params.Withdrawals != nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
+ } else {
+
+ if params.Withdrawals != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
+ }
}
+
if api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number)) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("newPayloadV2 called post-cancun"))
}
@@ -472,23 +509,26 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
+ if params.Withdrawals == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
+ }
if params.ExcessBlobGas == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
}
if params.BlobGasUsed == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil params.BlobGasUsed post-cancun"))
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
}
+
if versionedHashes == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
}
if beaconRoot == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil parentBeaconBlockRoot post-cancun"))
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}
if !api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number)) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 called pre-cancun"))
}
-
return api.newPayload(params, versionedHashes, beaconRoot)
}
@@ -775,6 +815,23 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
return caps
}
+// GetClientVersionV1 exchanges client version data of this node.
+func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engine.ClientVersionV1 {
+ log.Trace("Engine API request received", "method", "GetClientVersionV1", "info", info.String())
+ commit := make([]byte, 4)
+ if vcs, ok := version.VCS(); ok {
+ commit = common.FromHex(vcs.Commit)[0:4]
+ }
+ return []engine.ClientVersionV1{
+ {
+ Code: engine.ClientCode,
+ Name: engine.ClientName,
+ Version: params.VersionWithMeta,
+ Commit: hexutil.Encode(commit),
+ },
+ }
+}
+
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
// of block bodies by the engine api.
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
@@ -821,8 +878,7 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
)
for j, tx := range body.Transactions {
- data, _ := tx.MarshalBinary()
- txs[j] = hexutil.Bytes(data)
+ txs[j], _ = tx.MarshalBinary()
}
// Post-shanghai withdrawals MUST be set to empty slice instead of nil
diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go
index 3e95b57eba..b4d6534c90 100644
--- a/eth/catalyst/api_test.go
+++ b/eth/catalyst/api_test.go
@@ -71,7 +71,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
}
genesis := &core.Genesis{
Config: &config,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
testAddr: {Balance: testBalance},
params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")},
},
@@ -210,6 +210,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
FeeRecipient: blockParams.SuggestedFeeRecipient,
Random: blockParams.Random,
BeaconRoot: blockParams.BeaconRoot,
+ Version: engine.PayloadV1,
}).Id()
execData, err := api.GetPayloadV1(payloadID)
if err != nil {
@@ -261,11 +262,8 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
{0, true},
{parent.Time, true},
{parent.Time - 1, true},
-
- // TODO (MariusVanDerWijden) following tests are currently broken,
- // fixed in upcoming merge-kiln-v2 pr
- //{parent.Time() + 1, false},
- //{uint64(time.Now().Unix()) + uint64(time.Minute), false},
+ {parent.Time + 1, false},
+ {uint64(time.Now().Unix()) + uint64(time.Minute), false},
}
for i, test := range tests {
@@ -1588,7 +1586,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
fcState := engine.ForkchoiceStateV1{
HeadBlockHash: parent.Hash(),
}
- resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams)
+ resp, err := api.ForkchoiceUpdatedV3(fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData())
}
@@ -1604,6 +1602,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
Random: blockParams.Random,
Withdrawals: blockParams.Withdrawals,
BeaconRoot: blockParams.BeaconRoot,
+ Version: engine.PayloadV3,
}).Id()
execData, err := api.GetPayloadV3(payloadID)
if err != nil {
@@ -1643,3 +1642,26 @@ func TestParentBeaconBlockRoot(t *testing.T) {
t.Fatalf("incorrect root stored: want %s, got %s", *blockParams.BeaconRoot, root)
}
}
+
+// TestGetClientVersion verifies the expected version info is returned.
+func TestGetClientVersion(t *testing.T) {
+ genesis, preMergeBlocks := generateMergeChain(10, false)
+ n, ethservice := startEthService(t, genesis, preMergeBlocks)
+ defer n.Close()
+
+ api := NewConsensusAPI(ethservice)
+ info := engine.ClientVersionV1{
+ Code: "TT",
+ Name: "test",
+ Version: "1.1.1",
+ Commit: "0x12345678",
+ }
+ infos := api.GetClientVersionV1(info)
+ if len(infos) != 1 {
+ t.Fatalf("expected only one returned client version, got %d", len(infos))
+ }
+ info = infos[0]
+ if info.Code != engine.ClientCode || info.Name != engine.ClientName || info.Version != params.VersionWithMeta {
+ t.Fatalf("client info does match expected, got %s", info.String())
+ }
+}
diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go
index d8b8641e6a..f1c5689e1d 100644
--- a/eth/catalyst/simulated_beacon.go
+++ b/eth/catalyst/simulated_beacon.go
@@ -19,16 +19,18 @@ package catalyst
import (
"crypto/rand"
"errors"
+ "math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -81,6 +83,11 @@ type SimulatedBeacon struct {
lastBlockTime uint64
}
+// NewSimulatedBeacon constructs a new simulated beacon chain.
+// Period sets the period in which blocks should be produced.
+//
+// - If period is set to 0, a block is produced on every transaction.
+// via Commit, Fork and AdjustTime.
func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) {
block := eth.BlockChain().CurrentBlock()
current := engine.ForkchoiceStateV1{
@@ -116,7 +123,9 @@ func (c *SimulatedBeacon) setFeeRecipient(feeRecipient common.Address) {
// Start invokes the SimulatedBeacon life-cycle function in a goroutine.
func (c *SimulatedBeacon) Start() error {
if c.period == 0 {
- go c.loopOnDemand()
+ // if period is set to 0, do not mine at all
+ // this is used in the simulated backend where blocks
+ // are explicitly mined via Commit, AdjustTime and Fork
} else {
go c.loop()
}
@@ -131,10 +140,9 @@ func (c *SimulatedBeacon) Stop() error {
// sealBlock initiates payload building for a new block and creates a new block
// with the completed payload.
-func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
- tstamp := uint64(time.Now().Unix())
- if tstamp <= c.lastBlockTime {
- tstamp = c.lastBlockTime + 1
+func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp uint64) error {
+ if timestamp <= c.lastBlockTime {
+ timestamp = c.lastBlockTime + 1
}
c.feeRecipientLock.Lock()
feeRecipient := c.feeRecipient
@@ -148,12 +156,12 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
var random [32]byte
rand.Read(random[:])
- fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{
- Timestamp: tstamp,
+ fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
+ Timestamp: timestamp,
SuggestedFeeRecipient: feeRecipient,
Withdrawals: withdrawals,
Random: random,
- })
+ }, engine.PayloadV2, true)
if err != nil {
return err
}
@@ -183,6 +191,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
return err
}
c.setCurrentState(payload.BlockHash, finalizedHash)
+
// Mark the block containing the payload as canonical
if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
return err
@@ -191,32 +200,6 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
return nil
}
-// loopOnDemand runs the block production loop for "on-demand" configuration (period = 0)
-func (c *SimulatedBeacon) loopOnDemand() {
- var (
- newTxs = make(chan core.NewTxsEvent)
- sub = c.eth.TxPool().SubscribeTransactions(newTxs, true)
- )
- defer sub.Unsubscribe()
-
- for {
- select {
- case <-c.shutdownCh:
- return
- case w := <-c.withdrawals.pending:
- withdrawals := append(c.withdrawals.gatherPending(9), w)
- if err := c.sealBlock(withdrawals); err != nil {
- log.Warn("Error performing sealing work", "err", err)
- }
- case <-newTxs:
- withdrawals := c.withdrawals.gatherPending(10)
- if err := c.sealBlock(withdrawals); err != nil {
- log.Warn("Error performing sealing work", "err", err)
- }
- }
- }
-}
-
// loop runs the block production loop for non-zero period configuration
func (c *SimulatedBeacon) loop() {
timer := time.NewTimer(0)
@@ -226,7 +209,7 @@ func (c *SimulatedBeacon) loop() {
return
case <-timer.C:
withdrawals := c.withdrawals.gatherPending(10)
- if err := c.sealBlock(withdrawals); err != nil {
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
log.Warn("Error performing sealing work", "err", err)
} else {
timer.Reset(time.Second * time.Duration(c.period))
@@ -235,8 +218,8 @@ func (c *SimulatedBeacon) loop() {
}
}
-// finalizedBlockHash returns the block hash of the finalized block corresponding to the given number
-// or nil if doesn't exist in the chain.
+// finalizedBlockHash returns the block hash of the finalized block corresponding
+// to the given number or nil if doesn't exist in the chain.
func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
var finalizedNumber uint64
if number%devEpochLength == 0 {
@@ -244,7 +227,6 @@ func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
} else {
finalizedNumber = (number - 1) / devEpochLength * devEpochLength
}
-
if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil {
fh := finalizedBlock.Hash()
return &fh
@@ -261,11 +243,60 @@ func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) {
}
}
+// Commit seals a block on demand.
+func (c *SimulatedBeacon) Commit() common.Hash {
+ withdrawals := c.withdrawals.gatherPending(10)
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ return c.eth.BlockChain().CurrentBlock().Hash()
+}
+
+// Rollback un-sends previously added transactions.
+func (c *SimulatedBeacon) Rollback() {
+ // Flush all transactions from the transaction pools
+ maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
+ c.eth.TxPool().SetGasTip(maxUint256)
+ // Set the gas tip back to accept new transactions
+ // TODO (Marius van der Wijden): set gas tip to parameter passed by config
+ c.eth.TxPool().SetGasTip(big.NewInt(params.GWei))
+}
+
+// Fork sets the head to the provided hash.
+func (c *SimulatedBeacon) Fork(parentHash common.Hash) error {
+ if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 {
+ return errors.New("pending block dirty")
+ }
+ parent := c.eth.BlockChain().GetBlockByHash(parentHash)
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ return c.eth.BlockChain().SetHead(parent.NumberU64())
+}
+
+// AdjustTime creates a new block with an adjusted timestamp.
+func (c *SimulatedBeacon) AdjustTime(adjustment time.Duration) error {
+ if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 {
+ return errors.New("could not adjust time on non-empty block")
+ }
+ parent := c.eth.BlockChain().CurrentBlock()
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ withdrawals := c.withdrawals.gatherPending(10)
+ return c.sealBlock(withdrawals, parent.Time+uint64(adjustment))
+}
+
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
+ api := &api{sim}
+ if sim.period == 0 {
+ // mine on demand if period is set to 0
+ go api.loop()
+ }
stack.RegisterAPIs([]rpc.API{
{
Namespace: "dev",
- Service: &api{sim},
+ Service: api,
Version: "1.0",
},
})
diff --git a/eth/catalyst/simulated_beacon_api.go b/eth/catalyst/simulated_beacon_api.go
index 93670257f6..73d0a5921d 100644
--- a/eth/catalyst/simulated_beacon_api.go
+++ b/eth/catalyst/simulated_beacon_api.go
@@ -18,19 +18,44 @@ package catalyst
import (
"context"
+ "time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
)
type api struct {
- simBeacon *SimulatedBeacon
+ sim *SimulatedBeacon
+}
+
+func (a *api) loop() {
+ var (
+ newTxs = make(chan core.NewTxsEvent)
+ sub = a.sim.eth.TxPool().SubscribeTransactions(newTxs, true)
+ )
+ defer sub.Unsubscribe()
+
+ for {
+ select {
+ case <-a.sim.shutdownCh:
+ return
+ case w := <-a.sim.withdrawals.pending:
+ withdrawals := append(a.sim.withdrawals.gatherPending(9), w)
+ if err := a.sim.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ case <-newTxs:
+ a.sim.Commit()
+ }
+ }
}
func (a *api) AddWithdrawal(ctx context.Context, withdrawal *types.Withdrawal) error {
- return a.simBeacon.withdrawals.add(withdrawal)
+ return a.sim.withdrawals.add(withdrawal)
}
func (a *api) SetFeeRecipient(ctx context.Context, feeRecipient common.Address) {
- a.simBeacon.setFeeRecipient(feeRecipient)
+ a.sim.setFeeRecipient(feeRecipient)
}
diff --git a/eth/downloader/api.go b/eth/downloader/api.go
index 27cea07233..6b8cb98e23 100644
--- a/eth/downloader/api.go
+++ b/eth/downloader/api.go
@@ -19,51 +19,80 @@ package downloader
import (
"context"
"sync"
+ "time"
"github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc"
)
-// DownloaderAPI provides an API which gives information about the current synchronisation status.
-// It offers only methods that operates on data that can be available to anyone without security risks.
+// DownloaderAPI provides an API which gives information about the current
+// synchronisation status. It offers only methods that operates on data that
+// can be available to anyone without security risks.
type DownloaderAPI struct {
d *Downloader
+ chain *core.BlockChain
mux *event.TypeMux
installSyncSubscription chan chan interface{}
uninstallSyncSubscription chan *uninstallSyncSubscriptionRequest
}
-// NewDownloaderAPI create a new DownloaderAPI. The API has an internal event loop that
+// NewDownloaderAPI creates a new DownloaderAPI. The API has an internal event loop that
// listens for events from the downloader through the global event mux. In case it receives one of
// these events it broadcasts it to all syncing subscriptions that are installed through the
// installSyncSubscription channel.
-// nolint: staticcheck
-func NewDownloaderAPI(d *Downloader, m *event.TypeMux) *DownloaderAPI {
+func NewDownloaderAPI(d *Downloader, chain *core.BlockChain, m *event.TypeMux) *DownloaderAPI {
api := &DownloaderAPI{
d: d,
+ chain: chain,
mux: m,
installSyncSubscription: make(chan chan interface{}),
uninstallSyncSubscription: make(chan *uninstallSyncSubscriptionRequest),
}
-
go api.eventLoop()
-
return api
}
-// eventLoop runs a loop until the event mux closes. It will install and uninstall new
-// sync subscriptions and broadcasts sync status updates to the installed sync subscriptions.
+// eventLoop runs a loop until the event mux closes. It will install and uninstall
+// new sync subscriptions and broadcasts sync status updates to the installed sync
+// subscriptions.
+//
+// The sync status pushed to subscriptions can be a stream like:
+// >>> {Syncing: true, Progress: {...}}
+// >>> {false}
+//
+// If the node is already synced up, then only a single event subscribers will
+// receive is {false}.
func (api *DownloaderAPI) eventLoop() {
var (
- sub = api.mux.Subscribe(StartEvent{}, DoneEvent{}, FailedEvent{})
+ sub = api.mux.Subscribe(StartEvent{})
syncSubscriptions = make(map[chan interface{}]struct{})
+ checkInterval = time.Second * 60
+ checkTimer = time.NewTimer(checkInterval)
+
+ // status flags
+ started bool
+ done bool
+
+ getProgress = func() ethereum.SyncProgress {
+ prog := api.d.Progress()
+ if txProg, err := api.chain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
+ }
)
+ defer checkTimer.Stop()
for {
select {
case i := <-api.installSyncSubscription:
syncSubscriptions[i] = struct{}{}
+ if done {
+ i <- false
+ }
case u := <-api.uninstallSyncSubscription:
delete(syncSubscriptions, u.c)
close(u.uninstalled)
@@ -71,21 +100,31 @@ func (api *DownloaderAPI) eventLoop() {
if event == nil {
return
}
-
- var notification interface{}
switch event.Data.(type) {
case StartEvent:
- notification = &SyncingResult{
+ started = true
+ }
+ case <-checkTimer.C:
+ if !started {
+ checkTimer.Reset(checkInterval)
+ continue
+ }
+ prog := getProgress()
+ if !prog.Done() {
+ notification := &SyncingResult{
Syncing: true,
- Status: api.d.Progress(),
+ Status: prog,
}
- case DoneEvent, FailedEvent:
- notification = false
+ for c := range syncSubscriptions {
+ c <- notification
+ }
+ checkTimer.Reset(checkInterval)
+ continue
}
- // broadcast
for c := range syncSubscriptions {
- c <- notification
+ c <- false
}
+ done = true
}
}
}
@@ -102,16 +141,15 @@ func (api *DownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error
go func() {
statuses := make(chan interface{})
sub := api.SubscribeSyncStatus(statuses)
+ defer sub.Unsubscribe()
for {
select {
case status := <-statuses:
notifier.Notify(rpcSub.ID, status)
case <-rpcSub.Err():
- sub.Unsubscribe()
return
case <-notifier.Closed():
- sub.Unsubscribe()
return
}
}
diff --git a/eth/downloader/beaconsync.go b/eth/downloader/beaconsync.go
index e791db998c..a5d216e410 100644
--- a/eth/downloader/beaconsync.go
+++ b/eth/downloader/beaconsync.go
@@ -50,7 +50,8 @@ func newBeaconBackfiller(dl *Downloader, success func()) backfiller {
}
// suspend cancels any background downloader threads and returns the last header
-// that has been successfully backfilled.
+// that has been successfully backfilled (potentially in a previous run), or the
+// genesis.
func (b *beaconBackfiller) suspend() *types.Header {
// If no filling is running, don't waste cycles
b.lock.Lock()
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 4773275a1b..5f8d43a945 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -36,7 +36,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -221,7 +221,7 @@ type BlockChain interface {
// TrieDB retrieves the low level trie database used for interacting
// with trie nodes.
- TrieDB() *trie.Database
+ TrieDB() *triedb.Database
}
// New creates a new downloader to fetch hashes and blocks from remote peers.
@@ -662,6 +662,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
if err := d.lightchain.SetHead(origin); err != nil {
return err
}
+ log.Info("Truncated excess ancient chain segment", "oldhead", frozen-1, "newhead", origin)
}
}
// Initiate the sync using a concurrent header and content retrieval algorithm
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index 46d58f315b..c838510f17 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -41,8 +41,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
-
- "github.com/stretchr/testify/assert"
)
// downloadTester is a test simulator for mocking out local block chain.
@@ -78,7 +76,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
gspec := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
@@ -485,9 +483,6 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) }
func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) }
func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) }
-func TestCanonicalSynchronisation67Full(t *testing.T) { testCanonSync(t, eth.ETH67, FullSync) }
-func TestCanonicalSynchronisation67Snap(t *testing.T) { testCanonSync(t, eth.ETH67, SnapSync) }
-func TestCanonicalSynchronisation67Light(t *testing.T) { testCanonSync(t, eth.ETH67, LightSync) }
func testCanonSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -509,8 +504,6 @@ func testCanonSync(t *testing.T, protocol uint, mode SyncMode) {
// until the cached blocks are retrieved.
func TestThrottling68Full(t *testing.T) { testThrottling(t, eth.ETH68, FullSync) }
func TestThrottling68Snap(t *testing.T) { testThrottling(t, eth.ETH68, SnapSync) }
-func TestThrottling67Full(t *testing.T) { testThrottling(t, eth.ETH67, FullSync) }
-func TestThrottling67Snap(t *testing.T) { testThrottling(t, eth.ETH67, SnapSync) }
func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -597,9 +590,6 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) }
func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) }
func TestForkedSync68Light(t *testing.T) { testForkedSync(t, eth.ETH68, LightSync) }
-func TestForkedSync67Full(t *testing.T) { testForkedSync(t, eth.ETH67, FullSync) }
-func TestForkedSync67Snap(t *testing.T) { testForkedSync(t, eth.ETH67, SnapSync) }
-func TestForkedSync67Light(t *testing.T) { testForkedSync(t, eth.ETH67, LightSync) }
func testForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -629,9 +619,6 @@ func testForkedSync(t *testing.T, protocol uint, mode SyncMode) {
func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) }
func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) }
func TestHeavyForkedSync68Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, LightSync) }
-func TestHeavyForkedSync67Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, FullSync) }
-func TestHeavyForkedSync67Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, SnapSync) }
-func TestHeavyForkedSync67Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, LightSync) }
func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -663,9 +650,6 @@ func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) }
func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) }
func TestBoundedForkedSync68Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, LightSync) }
-func TestBoundedForkedSync67Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, FullSync) }
-func TestBoundedForkedSync67Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, SnapSync) }
-func TestBoundedForkedSync67Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, LightSync) }
func testBoundedForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -702,18 +686,6 @@ func TestBoundedHeavyForkedSync68Snap(t *testing.T) {
func TestBoundedHeavyForkedSync68Light(t *testing.T) {
testBoundedHeavyForkedSync(t, eth.ETH68, LightSync)
}
-func TestBoundedHeavyForkedSync67Full(t *testing.T) {
- t.Parallel()
- testBoundedHeavyForkedSync(t, eth.ETH67, FullSync)
-}
-func TestBoundedHeavyForkedSync67Snap(t *testing.T) {
- t.Parallel()
- testBoundedHeavyForkedSync(t, eth.ETH67, SnapSync)
-}
-func TestBoundedHeavyForkedSync67Light(t *testing.T) {
- t.Parallel()
- testBoundedHeavyForkedSync(t, eth.ETH67, LightSync)
-}
func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -743,9 +715,6 @@ func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) }
func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) }
func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) }
-func TestCancel67Full(t *testing.T) { testCancel(t, eth.ETH67, FullSync) }
-func TestCancel67Snap(t *testing.T) { testCancel(t, eth.ETH67, SnapSync) }
-func TestCancel67Light(t *testing.T) { testCancel(t, eth.ETH67, LightSync) }
func testCancel(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -776,9 +745,6 @@ func testCancel(t *testing.T, protocol uint, mode SyncMode) {
func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) }
func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) }
func TestMultiSynchronisation68Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, LightSync) }
-func TestMultiSynchronisation67Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, FullSync) }
-func TestMultiSynchronisation67Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, SnapSync) }
-func TestMultiSynchronisation67Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, LightSync) }
func testMultiSynchronisation(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -805,9 +771,6 @@ func testMultiSynchronisation(t *testing.T, protocol uint, mode SyncMode) {
func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) }
func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) }
func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) }
-func TestMultiProtoSynchronisation67Full(t *testing.T) { testMultiProtoSync(t, eth.ETH67, FullSync) }
-func TestMultiProtoSynchronisation67Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH67, SnapSync) }
-func TestMultiProtoSynchronisation67Light(t *testing.T) { testMultiProtoSync(t, eth.ETH67, LightSync) }
func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -818,7 +781,6 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
// Create peers of every type
tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:])
- tester.newPeer("peer 67", eth.ETH67, chain.blocks[1:])
// Synchronise with the requested peer and make sure all blocks were retrieved
if err := tester.sync(fmt.Sprintf("peer %d", protocol), nil, mode); err != nil {
@@ -828,7 +790,7 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
assertOwnChain(t, tester, len(chain.blocks))
// Check that no peers have been dropped off
- for _, version := range []int{68, 67} {
+ for _, version := range []int{68} {
peer := fmt.Sprintf("peer %d", version)
if _, ok := tester.peers[peer]; !ok {
t.Errorf("%s dropped", peer)
@@ -841,9 +803,6 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) }
func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) }
func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) }
-func TestEmptyShortCircuit67Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, FullSync) }
-func TestEmptyShortCircuit67Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, SnapSync) }
-func TestEmptyShortCircuit67Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, LightSync) }
func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -898,9 +857,6 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) }
func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) }
func TestMissingHeaderAttack68Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, LightSync) }
-func TestMissingHeaderAttack67Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, FullSync) }
-func TestMissingHeaderAttack67Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, SnapSync) }
-func TestMissingHeaderAttack67Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, LightSync) }
func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -929,9 +885,6 @@ func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) }
func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) }
func TestShiftedHeaderAttack68Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, LightSync) }
-func TestShiftedHeaderAttack67Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, FullSync) }
-func TestShiftedHeaderAttack67Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, SnapSync) }
-func TestShiftedHeaderAttack67Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, LightSync) }
func testShiftedHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -967,18 +920,6 @@ func TestHighTDStarvationAttack68Snap(t *testing.T) {
func TestHighTDStarvationAttack68Light(t *testing.T) {
testHighTDStarvationAttack(t, eth.ETH68, LightSync)
}
-func TestHighTDStarvationAttack67Full(t *testing.T) {
- t.Parallel()
- testHighTDStarvationAttack(t, eth.ETH67, FullSync)
-}
-func TestHighTDStarvationAttack67Snap(t *testing.T) {
- t.Parallel()
- testHighTDStarvationAttack(t, eth.ETH67, SnapSync)
-}
-func TestHighTDStarvationAttack67Light(t *testing.T) {
- t.Parallel()
- testHighTDStarvationAttack(t, eth.ETH67, LightSync)
-}
func testHighTDStarvationAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -994,7 +935,6 @@ func testHighTDStarvationAttack(t *testing.T, protocol uint, mode SyncMode) {
// Tests that misbehaving peers are disconnected, whilst behaving ones are not.
func TestBlockHeaderAttackerDropping68(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH68) }
-func TestBlockHeaderAttackerDropping67(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH67) }
func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
// Define the disconnection requirement for individual hash fetch errors
@@ -1048,9 +988,6 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) }
func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) }
func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) }
-func TestSyncProgress67Full(t *testing.T) { testSyncProgress(t, eth.ETH67, FullSync) }
-func TestSyncProgress67Snap(t *testing.T) { testSyncProgress(t, eth.ETH67, SnapSync) }
-func TestSyncProgress67Light(t *testing.T) { testSyncProgress(t, eth.ETH67, LightSync) }
func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1135,9 +1072,6 @@ func checkProgress(t *testing.T, d *Downloader, stage string, want ethereum.Sync
func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) }
func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) }
func TestForkedSyncProgress68Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, LightSync) }
-func TestForkedSyncProgress67Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, FullSync) }
-func TestForkedSyncProgress67Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestForkedSyncProgress67Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, LightSync) }
func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1217,9 +1151,6 @@ func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) }
func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) }
func TestFailedSyncProgress68Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, LightSync) }
-func TestFailedSyncProgress67Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, FullSync) }
-func TestFailedSyncProgress67Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestFailedSyncProgress67Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, LightSync) }
func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1294,9 +1225,6 @@ func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) }
func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) }
func TestFakedSyncProgress68Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, LightSync) }
-func TestFakedSyncProgress67Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, FullSync) }
-func TestFakedSyncProgress67Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestFakedSyncProgress67Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, LightSync) }
func testFakedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1461,8 +1389,6 @@ func TestRemoteHeaderRequestSpan(t *testing.T) {
// being fast-synced from, avoiding potential cheap eclipse attacks.
func TestBeaconSync68Full(t *testing.T) { testBeaconSync(t, eth.ETH68, FullSync) }
func TestBeaconSync68Snap(t *testing.T) { testBeaconSync(t, eth.ETH68, SnapSync) }
-func TestBeaconSync67Full(t *testing.T) { testBeaconSync(t, eth.ETH67, FullSync) }
-func TestBeaconSync67Snap(t *testing.T) { testBeaconSync(t, eth.ETH67, SnapSync) }
func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) {
t.Helper()
@@ -1572,119 +1498,3 @@ func (w *whitelistFake) RemoveMilestoneID(milestoneId string) {
func (w *whitelistFake) GetMilestoneIDsList() []string {
return nil
}
-
-// TestFakedSyncProgress67WhitelistMismatch tests if in case of whitelisted
-// checkpoint mismatch with opposite peer, the sync should fail.
-func TestFakedSyncProgress67WhitelistMismatch(t *testing.T) {
- t.Parallel()
-
- protocol := uint(eth.ETH67)
- mode := FullSync
-
- tester := newTester(t)
- validate := func(count int) (bool, error) {
- return false, whitelist.ErrMismatch
- }
- tester.downloader.ChainValidator = newWhitelistFake(validate)
-
- defer tester.terminate()
-
- chainA := testChainForkLightA.blocks
- tester.newPeer("light", protocol, chainA[1:])
-
- // Synchronise with the peer and make sure all blocks were retrieved
- if err := tester.sync("light", nil, mode); err == nil {
- t.Fatal("succeeded attacker synchronisation")
- }
-}
-
-// TestFakedSyncProgress67WhitelistMatch tests if in case of whitelisted
-// checkpoint match with opposite peer, the sync should succeed.
-func TestFakedSyncProgress67WhitelistMatch(t *testing.T) {
- t.Parallel()
-
- protocol := uint(eth.ETH67)
- mode := FullSync
-
- tester := newTester(t)
- validate := func(count int) (bool, error) {
- return true, nil
- }
- tester.downloader.ChainValidator = newWhitelistFake(validate)
-
- defer tester.terminate()
-
- chainA := testChainForkLightA.blocks
- tester.newPeer("light", protocol, chainA[1:])
-
- // Synchronise with the peer and make sure all blocks were retrieved
- if err := tester.sync("light", nil, mode); err != nil {
- t.Fatal("succeeded attacker synchronisation")
- }
-}
-
-// TestFakedSyncProgress67NoRemoteCheckpoint tests if in case of missing/invalid
-// checkpointed blocks with opposite peer, the sync should fail initially but
-// with the retry mechanism, it should succeed eventually.
-func TestFakedSyncProgress67NoRemoteCheckpoint(t *testing.T) {
- t.Parallel()
-
- protocol := uint(eth.ETH67)
- mode := FullSync
-
- tester := newTester(t)
- validate := func(count int) (bool, error) {
- // only return the `ErrNoRemoteCheckpoint` error for the first call
- if count == 0 {
- return false, whitelist.ErrNoRemote
- }
-
- return true, nil
- }
-
- tester.downloader.ChainValidator = newWhitelistFake(validate)
-
- defer tester.terminate()
-
- chainA := testChainForkLightA.blocks
- tester.newPeer("light", protocol, chainA[1:])
-
- // Set the max validation threshold equal to chain length to enforce validation
- tester.downloader.maxValidationThreshold = uint64(len(chainA) - 1)
-
- // Synchronise with the peer and make sure all blocks were retrieved
- // Should fail in first attempt
- err := tester.sync("light", nil, mode)
- assert.Equal(t, whitelist.ErrNoRemote, err, "failed synchronisation")
-
- // Try syncing again, should succeed
- if err := tester.sync("light", nil, mode); err != nil {
- t.Fatal("succeeded attacker synchronisation")
- }
-}
-
-// TestFakedSyncProgress67BypassWhitelistValidation tests if peer validation
-// via whitelist is bypassed when remote peer is far away or not
-func TestFakedSyncProgress67BypassWhitelistValidation(t *testing.T) {
- protocol := uint(eth.ETH67)
- mode := FullSync
-
- tester := newTester(t)
- validate := func(count int) (bool, error) {
- return false, whitelist.ErrNoRemote
- }
-
- tester.downloader.ChainValidator = newWhitelistFake(validate)
-
- defer tester.terminate()
-
- // 1223 length chain
- chainA := testChainBase.blocks
- tester.newPeer("light", protocol, chainA[1:])
-
- // Although the validate function above returns an error (which says that
- // remote peer doesn't have that block), sync will go through as the chain
- // import length is 1223 which is more than the default threshold of 1024
- err := tester.sync("light", nil, mode)
- assert.NoError(t, err, "failed synchronisation")
-}
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index 77045a6f1d..089b1616dc 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
@@ -867,7 +868,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
return errInvalidBody
}
for _, hash := range tx.BlobHashes() {
- if hash[0] != params.BlobTxHashVersion {
+ if !kzg4844.IsValidVersionedHash(hash[:]) {
return errInvalidBody
}
}
diff --git a/eth/downloader/skeleton.go b/eth/downloader/skeleton.go
index 3a91f1ac7e..bfd1c34bf2 100644
--- a/eth/downloader/skeleton.go
+++ b/eth/downloader/skeleton.go
@@ -161,7 +161,7 @@ type backfiller interface {
// on initial startup.
//
// The method should return the last block header that has been successfully
- // backfilled, or nil if the backfiller was not resumed.
+ // backfilled (in the current or a previous run), falling back to the genesis.
suspend() *types.Header
// resume requests the backfiller to start running fill or snap sync based on
@@ -388,14 +388,17 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
done := make(chan struct{})
go func() {
defer close(done)
- if filled := s.filler.suspend(); filled != nil {
- // If something was filled, try to delete stale sync helpers. If
- // unsuccessful, warn the user, but not much else we can do (it's
- // a programming error, just let users report an issue and don't
- // choke in the meantime).
- if err := s.cleanStales(filled); err != nil {
- log.Error("Failed to clean stale beacon headers", "err", err)
- }
+ filled := s.filler.suspend()
+ if filled == nil {
+ log.Error("Latest filled block is not available")
+ return
+ }
+ // If something was filled, try to delete stale sync helpers. If
+ // unsuccessful, warn the user, but not much else we can do (it's
+ // a programming error, just let users report an issue and don't
+ // choke in the meantime).
+ if err := s.cleanStales(filled); err != nil {
+ log.Error("Failed to clean stale beacon headers", "err", err)
}
}()
// Wait for the suspend to finish, consuming head events in the meantime
@@ -1177,34 +1180,46 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
number := filled.Number.Uint64()
log.Trace("Cleaning stale beacon headers", "filled", number, "hash", filled.Hash())
- // If the filled header is below the linked subchain, something's
- // corrupted internally. Report and error and refuse to do anything.
- if number < s.progress.Subchains[0].Tail {
+ // If the filled header is below the linked subchain, something's corrupted
+ // internally. Report and error and refuse to do anything.
+ if number+1 < s.progress.Subchains[0].Tail {
return fmt.Errorf("filled header below beacon header tail: %d < %d", number, s.progress.Subchains[0].Tail)
}
- // Subchain seems trimmable, push the tail forward up to the last
- // filled header and delete everything before it - if available. In
- // case we filled past the head, recreate the subchain with a new
- // head to keep it consistent with the data on disk.
+ // If nothing in subchain is filled, don't bother to do cleanup.
+ if number+1 == s.progress.Subchains[0].Tail {
+ return nil
+ }
var (
- start = s.progress.Subchains[0].Tail // start deleting from the first known header
- end = number // delete until the requested threshold
+ start uint64
+ end uint64
batch = s.db.NewBatch()
)
+ if number < s.progress.Subchains[0].Head {
+ // The skeleton chain is partially consumed, set the new tail as filled+1.
+ tail := rawdb.ReadSkeletonHeader(s.db, number+1)
+ if tail.ParentHash != filled.Hash() {
+ return fmt.Errorf("filled header is discontinuous with subchain: %d %s, please file an issue", number, filled.Hash())
+ }
+ start, end = s.progress.Subchains[0].Tail, number+1 // remove headers in [tail, filled]
+ s.progress.Subchains[0].Tail = tail.Number.Uint64()
+ s.progress.Subchains[0].Next = tail.ParentHash
+ } else {
+ // The skeleton chain is fully consumed, set both head and tail as filled.
+ start, end = s.progress.Subchains[0].Tail, filled.Number.Uint64() // remove headers in [tail, filled)
+ s.progress.Subchains[0].Tail = filled.Number.Uint64()
+ s.progress.Subchains[0].Next = filled.ParentHash
- s.progress.Subchains[0].Tail = number
- s.progress.Subchains[0].Next = filled.ParentHash
+ // If more headers were filled than available, push the entire subchain
+ // forward to keep tracking the node's block imports.
+ if number > s.progress.Subchains[0].Head {
+ end = s.progress.Subchains[0].Head + 1 // delete the entire original range, including the head
+ s.progress.Subchains[0].Head = number // assign a new head (tail is already assigned to this)
- if s.progress.Subchains[0].Head < number {
- // If more headers were filled than available, push the entire
- // subchain forward to keep tracking the node's block imports
- end = s.progress.Subchains[0].Head + 1 // delete the entire original range, including the head
- s.progress.Subchains[0].Head = number // assign a new head (tail is already assigned to this)
-
- // The entire original skeleton chain was deleted and a new one
- // defined. Make sure the new single-header chain gets pushed to
- // disk to keep internal state consistent.
- rawdb.WriteSkeletonHeader(batch, filled)
+ // The entire original skeleton chain was deleted and a new one
+ // defined. Make sure the new single-header chain gets pushed to
+ // disk to keep internal state consistent.
+ rawdb.WriteSkeletonHeader(batch, filled)
+ }
}
// Execute the trimming and the potential rewiring of the progress
s.saveSyncStatus(batch)
diff --git a/eth/downloader/skeleton_test.go b/eth/downloader/skeleton_test.go
index 1054da209f..7b6da1a23b 100644
--- a/eth/downloader/skeleton_test.go
+++ b/eth/downloader/skeleton_test.go
@@ -832,7 +832,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
// Create a peer set to feed headers through
peerset := newPeerSet()
for _, peer := range tt.peers {
- peerset.Register(newPeerConnection(peer.id, eth.ETH67, peer, log.New("id", peer.id)))
+ peerset.Register(newPeerConnection(peer.id, eth.ETH68, peer, log.New("id", peer.id)))
}
// Create a peer dropper to track malicious peers
dropped := make(map[string]int)
@@ -948,7 +948,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
}
if tt.newPeer != nil {
- if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH67, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil {
+ if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH68, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil {
t.Errorf("test %d: failed to register new peer: %v", i, err)
}
}
diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go
index 38bcb2e7fe..dce375c8da 100644
--- a/eth/downloader/testchain_test.go
+++ b/eth/downloader/testchain_test.go
@@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// Test chain parameters.
@@ -41,10 +41,10 @@ var (
testGspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
- testGenesis = testGspec.MustCommit(testDB, trie.NewDatabase(testDB, trie.HashDefaults))
+ testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults))
)
// The common prefix of all test chains:
diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go
index 556fd73dbd..407fd70ad0 100644
--- a/eth/fetcher/block_fetcher_test.go
+++ b/eth/fetcher/block_fetcher_test.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -41,10 +42,10 @@ var (
testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
gspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
- genesis = gspec.MustCommit(testdb, trie.NewDatabase(testdb, trie.HashDefaults))
+ genesis = gspec.MustCommit(testdb, triedb.NewDatabase(testdb, triedb.HashDefaults))
unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit, BaseFee: big.NewInt(params.InitialBaseFee)}, nil, nil, nil, trie.NewStackTrie(nil))
)
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 42a8d303c1..ba785869a3 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -44,6 +44,9 @@ var (
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
const maxTopics = 4
+// The maximum number of allowed topics within a topic criteria
+const maxSubTopics = 1000
+
// filter is a helper struct that holds meta information over the filter type
// and associated subscription in the event system.
type filter struct {
@@ -169,6 +172,8 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
go func() {
txs := make(chan []*types.Transaction, 128)
pendingTxSub := api.events.SubscribePendingTxs(txs)
+ defer pendingTxSub.Unsubscribe()
+
chainConfig := api.sys.backend.ChainConfig()
for {
@@ -187,10 +192,8 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
}
}
case <-rpcSub.Err():
- pendingTxSub.Unsubscribe()
return
case <-notifier.Closed():
- pendingTxSub.Unsubscribe()
return
}
}
@@ -245,16 +248,15 @@ func (api *FilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) {
go func() {
headers := make(chan *types.Header)
headersSub := api.events.SubscribeNewHeads(headers)
+ defer headersSub.Unsubscribe()
for {
select {
case h := <-headers:
notifier.Notify(rpcSub.ID, h)
case <-rpcSub.Err():
- headersSub.Unsubscribe()
return
case <-notifier.Closed():
- headersSub.Unsubscribe()
return
}
}
@@ -281,6 +283,7 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
}
go func() {
+ defer logsSub.Unsubscribe()
for {
select {
case logs := <-matchedLogs:
@@ -289,10 +292,8 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
notifier.Notify(rpcSub.ID, &log)
}
case <-rpcSub.Err(): // client send an unsubscribe request
- logsSub.Unsubscribe()
return
case <-notifier.Closed(): // connection dropped
- logsSub.Unsubscribe()
return
}
}
@@ -629,6 +630,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
return errors.New("invalid addresses in query")
}
}
+ if len(raw.Topics) > maxTopics {
+ return errExceedMaxTopics
+ }
// topics is an array consisting of strings and/or arrays of strings.
// JSON null values are converted to common.Hash{} and ignored by the filter manager.
@@ -651,6 +655,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
case []interface{}:
// or case e.g. [null, "topic0", "topic1"]
+ if len(topic) > maxSubTopics {
+ return errExceedMaxTopics
+ }
for _, rawTopic := range topic {
if rawTopic == nil {
// null component, match all
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index e92e70b5e7..3e000984ee 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -892,7 +892,7 @@ func TestLightFilterLogs(t *testing.T) {
key, _ = crypto.GenerateKey()
addr = crypto.PubkeyToAddress(key.PublicKey)
genesis = &core.Genesis{Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
},
}
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index b61ec3f3a4..4eff382504 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -34,7 +34,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func makeReceipt(addr common.Address) *types.Receipt {
@@ -58,7 +58,7 @@ func BenchmarkFilters(b *testing.B) {
addr4 = common.BytesToAddress([]byte("random addresses please"))
gspec = &core.Genesis{
- Alloc: core.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
+ Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
@@ -89,7 +89,7 @@ func BenchmarkFilters(b *testing.B) {
// The test txs are not properly signed, can't simply create a chain
// and then import blocks. TODO(rjl493456442) try to get rid of the
// manual database writes.
- gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
for i, block := range chain {
rawdb.WriteBlock(db, block)
@@ -103,6 +103,7 @@ func BenchmarkFilters(b *testing.B) {
filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil)
for i := 0; i < b.N; i++ {
+ filter.begin = 0
logs, _ := filter.Logs(context.Background())
if len(logs) != 4 {
b.Fatal("expected 4 logs, got", len(logs))
@@ -168,7 +169,7 @@ func TestFilters(t *testing.T) {
gspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
contract: {Balance: big.NewInt(0), Code: bytecode},
contract2: {Balance: big.NewInt(0), Code: bytecode},
@@ -184,7 +185,7 @@ func TestFilters(t *testing.T) {
// Hack: GenerateChainWithGenesis creates a new db.
// Commit the genesis manually and use GenerateChain.
- _, err = gspec.Commit(db, trie.NewDatabase(db, nil))
+ _, err = gspec.Commit(db, triedb.NewDatabase(db, nil))
if err != nil {
t.Fatal(err)
}
diff --git a/eth/gasestimator/gasestimator.go b/eth/gasestimator/gasestimator.go
index 7e121cad02..db99a9a224 100644
--- a/eth/gasestimator/gasestimator.go
+++ b/eth/gasestimator/gasestimator.go
@@ -71,9 +71,9 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
}
// Recap the highest gas limit with account's available balance.
if feeCap.BitLen() != 0 {
- balance := opts.State.GetBalance(call.From)
+ balance := opts.State.GetBalance(call.From).ToBig()
- available := new(big.Int).Set(balance)
+ available := balance
if call.Value != nil {
if call.Value.Cmp(available) >= 0 {
return 0, nil, core.ErrInsufficientFundsForTransfer
diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go
index 371c9ea545..1ce6b6d929 100644
--- a/eth/gasprice/feehistory.go
+++ b/eth/gasprice/feehistory.go
@@ -243,7 +243,6 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
if p < 0 || p > 100 {
return common.Big0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
}
-
if i > 0 && p <= rewardPercentiles[i-1] {
return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f >= #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
}
diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go
index 61796355f2..4b6a62c78d 100644
--- a/eth/gasprice/gasprice_test.go
+++ b/eth/gasprice/gasprice_test.go
@@ -139,7 +139,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
config = *params.TestChainConfig // needs copy because it is modified below
gspec = &core.Genesis{
Config: &config,
- Alloc: core.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
+ Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
}
signer = types.LatestSigner(gspec.Config)
)
diff --git a/eth/handler.go b/eth/handler.go
index 1775f2df5c..3d1670f474 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -43,7 +43,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
const (
@@ -75,7 +75,7 @@ type txPool interface {
// Pending should return pending transactions.
// The slice should be modifiable by the caller.
- Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction
+ Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction
// SubscribeTransactions subscribes to new transaction events. The subscriber
// can decide whether to receive notifications only for newly seen transactions
diff --git a/eth/handler_eth.go b/eth/handler_eth.go
index 625010de89..12a60785d2 100644
--- a/eth/handler_eth.go
+++ b/eth/handler_eth.go
@@ -68,10 +68,7 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
case *eth.NewBlockPacket:
return h.handleBlockBroadcast(peer, packet.Block, packet.TD)
- case *eth.NewPooledTransactionHashesPacket67:
- return h.txFetcher.Notify(peer.ID(), nil, nil, *packet)
-
- case *eth.NewPooledTransactionHashesPacket68:
+ case *eth.NewPooledTransactionHashesPacket:
return h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes)
case *eth.TransactionsPacket:
diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go
index c44b4c9a33..6792bd4104 100644
--- a/eth/handler_eth_test.go
+++ b/eth/handler_eth_test.go
@@ -58,11 +58,7 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
h.blockBroadcasts.Send(packet.Block)
return nil
- case *eth.NewPooledTransactionHashesPacket67:
- h.txAnnounces.Send(([]common.Hash)(*packet))
- return nil
-
- case *eth.NewPooledTransactionHashesPacket68:
+ case *eth.NewPooledTransactionHashesPacket:
h.txAnnounces.Send(packet.Hashes)
return nil
@@ -81,7 +77,6 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
// Tests that peers are correctly accepted (or rejected) based on the advertised
// fork IDs in the protocol handshake.
-func TestForkIDSplit67(t *testing.T) { testForkIDSplit(t, eth.ETH67) }
func TestForkIDSplit68(t *testing.T) { testForkIDSplit(t, eth.ETH68) }
func testForkIDSplit(t *testing.T, protocol uint) {
@@ -241,7 +236,6 @@ func testForkIDSplit(t *testing.T, protocol uint) {
}
// Tests that received transactions are added to the local pool.
-func TestRecvTransactions67(t *testing.T) { testRecvTransactions(t, eth.ETH67) }
func TestRecvTransactions68(t *testing.T) { testRecvTransactions(t, eth.ETH68) }
func testRecvTransactions(t *testing.T, protocol uint) {
@@ -301,7 +295,6 @@ func testRecvTransactions(t *testing.T, protocol uint) {
}
// This test checks that pending transactions are sent.
-func TestSendTransactions67(t *testing.T) { testSendTransactions(t, eth.ETH67) }
func TestSendTransactions68(t *testing.T) { testSendTransactions(t, eth.ETH68) }
func testSendTransactions(t *testing.T, protocol uint) {
@@ -360,7 +353,7 @@ func testSendTransactions(t *testing.T, protocol uint) {
seen := make(map[common.Hash]struct{})
for len(seen) < len(insert) {
switch protocol {
- case 67, 68:
+ case 68:
select {
case hashes := <-anns:
for _, hash := range hashes {
@@ -386,7 +379,6 @@ func testSendTransactions(t *testing.T, protocol uint) {
// Tests that transactions get propagated to all attached peers, either via direct
// broadcasts or via announcements/retrievals.
-func TestTransactionPropagation67(t *testing.T) { testTransactionPropagation(t, eth.ETH67) }
func TestTransactionPropagation68(t *testing.T) { testTransactionPropagation(t, eth.ETH68) }
func testTransactionPropagation(t *testing.T, protocol uint) {
@@ -494,8 +486,8 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
defer sourcePipe.Close()
defer sinkPipe.Close()
- sourcePeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil)
- sinkPeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil)
+ sourcePeer := eth.NewPeer(eth.ETH68, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil)
+ sinkPeer := eth.NewPeer(eth.ETH68, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil)
defer sourcePeer.Close()
defer sinkPeer.Close()
@@ -554,7 +546,6 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
// Tests that a propagated malformed block (uncles or transactions don't match
// with the hashes in the header) gets discarded and not broadcast forward.
-func TestBroadcastMalformedBlock67(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH67) }
func TestBroadcastMalformedBlock68(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH68) }
func testBroadcastMalformedBlock(t *testing.T, protocol uint) {
diff --git a/eth/handler_test.go b/eth/handler_test.go
index 2625b4d138..df556e6c5a 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var (
@@ -92,7 +93,7 @@ func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []erro
}
// Pending returns all the transactions known to the pool
-func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction {
+func (p *testTxPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
p.lock.RLock()
defer p.lock.RUnlock()
@@ -112,8 +113,8 @@ func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.Lazy
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
@@ -150,7 +151,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
db := rawdb.NewMemoryDatabase()
gspec := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
+ Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
}
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
diff --git a/eth/peerset.go b/eth/peerset.go
index 369432e914..e5d486f2b3 100644
--- a/eth/peerset.go
+++ b/eth/peerset.go
@@ -57,6 +57,7 @@ type peerSet struct {
lock sync.RWMutex
closed bool
+ quitCh chan struct{} // Quit channel to signal termination
}
// newPeerSet creates a new peer set to track the active participants.
@@ -65,6 +66,7 @@ func newPeerSet() *peerSet {
peers: make(map[string]*ethPeer),
snapWait: make(map[string]chan *snap.Peer),
snapPend: make(map[string]*snap.Peer),
+ quitCh: make(chan struct{}),
}
}
@@ -135,7 +137,15 @@ func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
ps.snapWait[id] = wait
ps.lock.Unlock()
- return <-wait, nil
+ select {
+ case p := <-wait:
+ return p, nil
+ case <-ps.quitCh:
+ ps.lock.Lock()
+ delete(ps.snapWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerSetClosed
+ }
}
// registerPeer injects a new `eth` peer into the working set, or returns an error
@@ -275,6 +285,8 @@ func (ps *peerSet) close() {
for _, p := range ps.peers {
p.Disconnect(p2p.DiscQuitting)
}
-
+ if !ps.closed {
+ close(ps.quitCh)
+ }
ps.closed = true
}
diff --git a/eth/protocols/eth/broadcast.go b/eth/protocols/eth/broadcast.go
index 646a3c9163..b178bcb3fa 100644
--- a/eth/protocols/eth/broadcast.go
+++ b/eth/protocols/eth/broadcast.go
@@ -166,16 +166,9 @@ func (p *Peer) announceTransactions() {
if len(pending) > 0 {
done = make(chan struct{})
go func() {
- if p.version >= ETH68 {
- if err := p.sendPooledTransactionHashes68(pending, pendingTypes, pendingSizes); err != nil {
- fail <- err
- return
- }
- } else {
- if err := p.sendPooledTransactionHashes66(pending); err != nil {
- fail <- err
- return
- }
+ if err := p.sendPooledTransactionHashes(pending, pendingTypes, pendingSizes); err != nil {
+ fail <- err
+ return
}
close(done)
p.Log().Trace("Sent transaction announcements", "count", len(pending))
diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go
index e24a24b2a1..2d69ecdc83 100644
--- a/eth/protocols/eth/handler.go
+++ b/eth/protocols/eth/handler.go
@@ -93,10 +93,6 @@ type TxPool interface {
func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol {
protocols := make([]p2p.Protocol, 0, len(ProtocolVersions))
for _, version := range ProtocolVersions {
- // Blob transactions require eth/68 announcements, disable everything else
- if version <= ETH67 && backend.Chain().Config().CancunBlock != nil {
- continue
- }
version := version // Closure
protocols = append(protocols, p2p.Protocol{
@@ -166,26 +162,11 @@ type Decoder interface {
Time() time.Time
}
-var eth67 = map[uint64]msgHandler{
- NewBlockHashesMsg: handleNewBlockhashes,
- NewBlockMsg: handleNewBlock,
- TransactionsMsg: handleTransactions,
- NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes67,
- GetBlockHeadersMsg: handleGetBlockHeaders,
- BlockHeadersMsg: handleBlockHeaders,
- GetBlockBodiesMsg: handleGetBlockBodies,
- BlockBodiesMsg: handleBlockBodies,
- GetReceiptsMsg: handleGetReceipts,
- ReceiptsMsg: handleReceipts,
- GetPooledTransactionsMsg: handleGetPooledTransactions,
- PooledTransactionsMsg: handlePooledTransactions,
-}
-
var eth68 = map[uint64]msgHandler{
NewBlockHashesMsg: handleNewBlockhashes,
NewBlockMsg: handleNewBlock,
TransactionsMsg: handleTransactions,
- NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes68,
+ NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes,
GetBlockHeadersMsg: handleGetBlockHeaders,
BlockHeadersMsg: handleBlockHeaders,
GetBlockBodiesMsg: handleGetBlockBodies,
@@ -209,10 +190,8 @@ func handleMessage(backend Backend, peer *Peer) error {
}
defer msg.Discard()
- var handlers = eth67
- if peer.Version() >= ETH68 {
- handlers = eth68
- }
+ var handlers = eth68
+
// Track the amount of time it takes to serve the request and run the handler
if metrics.Enabled {
h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go
index 3c30df6b2e..94860a0e9a 100644
--- a/eth/protocols/eth/handler_test.go
+++ b/eth/protocols/eth/handler_test.go
@@ -102,7 +102,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
gspec := &core.Genesis{
Config: config,
- Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
+ Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
}
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
@@ -118,7 +118,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
txconfig.Journal = "" // Don't litter the disk with test journals
pool := legacypool.New(txconfig, chain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(txconfig.PriceLimit), chain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(txconfig.PriceLimit, chain, []txpool.SubPool{pool})
return &testBackend{
db: db,
@@ -151,7 +151,6 @@ func (b *testBackend) Handle(*Peer, Packet) error {
}
// Tests that block headers can be retrieved from a remote chain based on user queries.
-func TestGetBlockHeaders67(t *testing.T) { testGetBlockHeaders(t, ETH67) }
func TestGetBlockHeaders68(t *testing.T) { testGetBlockHeaders(t, ETH68) }
func testGetBlockHeaders(t *testing.T, protocol uint) {
@@ -339,7 +338,6 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
}
// Tests that block contents can be retrieved from a remote chain based on their hashes.
-func TestGetBlockBodies67(t *testing.T) { testGetBlockBodies(t, ETH67) }
func TestGetBlockBodies68(t *testing.T) { testGetBlockBodies(t, ETH68) }
func testGetBlockBodies(t *testing.T, protocol uint) {
@@ -434,7 +432,6 @@ func testGetBlockBodies(t *testing.T, protocol uint) {
}
// Tests that the transaction receipts can be retrieved based on hashes.
-func TestGetBlockReceipts67(t *testing.T) { testGetBlockReceipts(t, ETH67) }
func TestGetBlockReceipts68(t *testing.T) { testGetBlockReceipts(t, ETH68) }
func testGetBlockReceipts(t *testing.T, protocol uint) {
diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go
index e8f3fb7b8c..0ce5bd1a1a 100644
--- a/eth/protocols/eth/handlers.go
+++ b/eth/protocols/eth/handlers.go
@@ -425,33 +425,13 @@ func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
}, metadata)
}
-func handleNewPooledTransactionHashes67(backend Backend, msg Decoder, peer *Peer) error {
+func handleNewPooledTransactionHashes(backend Backend, msg Decoder, peer *Peer) error {
// New transaction announcement arrived, make sure we have
// a valid and fresh chain to handle them
if !backend.AcceptTxs() {
return nil
}
- ann := new(NewPooledTransactionHashesPacket67)
- if err := msg.Decode(ann); err != nil {
- return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
- }
- // Schedule all the unknown hashes for retrieval
- for _, hash := range *ann {
- peer.markTransaction(hash)
- }
-
- return backend.Handle(peer, ann)
-}
-
-func handleNewPooledTransactionHashes68(backend Backend, msg Decoder, peer *Peer) error {
- // New transaction announcement arrived, make sure we have
- // a valid and fresh chain to handle them
- if !backend.AcceptTxs() {
- return nil
- }
-
- ann := new(NewPooledTransactionHashesPacket68)
-
+ ann := new(NewPooledTransactionHashesPacket)
if err := msg.Decode(ann); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
diff --git a/eth/protocols/eth/handshake_test.go b/eth/protocols/eth/handshake_test.go
index 6089723e57..fa415cb7cf 100644
--- a/eth/protocols/eth/handshake_test.go
+++ b/eth/protocols/eth/handshake_test.go
@@ -27,7 +27,6 @@ import (
)
// Tests that handshake failures are detected and reported correctly.
-func TestHandshake67(t *testing.T) { testHandshake(t, ETH67) }
func TestHandshake68(t *testing.T) { testHandshake(t, ETH68) }
func testHandshake(t *testing.T, protocol uint) {
diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go
index 21fd966d58..bfd7f1ff46 100644
--- a/eth/protocols/eth/peer.go
+++ b/eth/protocols/eth/peer.go
@@ -92,7 +92,7 @@ type Peer struct {
lock sync.RWMutex // Mutex protecting the internal fields
}
-// NewPeer create a wrapper for a network connection and negotiated protocol
+// NewPeer creates a wrapper for a network connection and negotiated protocol
// version.
func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter, txpool TxPool) *Peer {
peer := &Peer{
@@ -210,29 +210,17 @@ func (p *Peer) AsyncSendTransactions(hashes []common.Hash) {
}
}
-// sendPooledTransactionHashes66 sends transaction hashes to the peer and includes
-// them in its transaction hash set for future reference.
-//
-// This method is a helper used by the async transaction announcer. Don't call it
-// directly as the queueing (memory) and transmission (bandwidth) costs should
-// not be managed directly.
-func (p *Peer) sendPooledTransactionHashes66(hashes []common.Hash) error {
- // Mark all the transactions as known, but ensure we don't overflow our limits
- p.knownTxs.Add(hashes...)
- return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket67(hashes))
-}
-
-// sendPooledTransactionHashes68 sends transaction hashes (tagged with their type
+// sendPooledTransactionHashes sends transaction hashes (tagged with their type
// and size) to the peer and includes them in its transaction hash set for future
// reference.
//
// This method is a helper used by the async transaction announcer. Don't call it
// directly as the queueing (memory) and transmission (bandwidth) costs should
// not be managed directly.
-func (p *Peer) sendPooledTransactionHashes68(hashes []common.Hash, types []byte, sizes []uint32) error {
+func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash, types []byte, sizes []uint32) error {
// Mark all the transactions as known, but ensure we don't overflow our limits
p.knownTxs.Add(hashes...)
- return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket68{Types: types, Sizes: sizes, Hashes: hashes})
+ return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket{Types: types, Sizes: sizes, Hashes: hashes})
}
// AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually
diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go
index 4b69c635ad..c0534b4da5 100644
--- a/eth/protocols/eth/protocol.go
+++ b/eth/protocols/eth/protocol.go
@@ -30,7 +30,6 @@ import (
// Constants to match up protocol versions and messages
const (
- ETH67 = 67
ETH68 = 68
)
@@ -40,11 +39,11 @@ const ProtocolName = "eth"
// ProtocolVersions are the supported versions of the `eth` protocol (first
// is primary).
-var ProtocolVersions = []uint{ETH68, ETH67}
+var ProtocolVersions = []uint{ETH68}
// protocolLengths are the number of implemented message corresponding to
// different protocol versions.
-var protocolLengths = map[uint]uint64{ETH68: 17, ETH67: 17}
+var protocolLengths = map[uint]uint64{ETH68: 17}
// maxMessageSize is the maximum cap on the size of a protocol message.
const maxMessageSize = 10 * 1024 * 1024
@@ -291,11 +290,8 @@ type ReceiptsRLPPacket struct {
ReceiptsRLPResponse
}
-// NewPooledTransactionHashesPacket67 represents a transaction announcement packet on eth/67.
-type NewPooledTransactionHashesPacket67 []common.Hash
-
-// NewPooledTransactionHashesPacket68 represents a transaction announcement packet on eth/68 and newer.
-type NewPooledTransactionHashesPacket68 struct {
+// NewPooledTransactionHashesPacket represents a transaction announcement packet on eth/68 and newer.
+type NewPooledTransactionHashesPacket struct {
Types []byte
Sizes []uint32
Hashes []common.Hash
@@ -354,10 +350,8 @@ func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg }
func (*NewBlockPacket) Name() string { return "NewBlock" }
func (*NewBlockPacket) Kind() byte { return NewBlockMsg }
-func (*NewPooledTransactionHashesPacket67) Name() string { return "NewPooledTransactionHashes" }
-func (*NewPooledTransactionHashesPacket67) Kind() byte { return NewPooledTransactionHashesMsg }
-func (*NewPooledTransactionHashesPacket68) Name() string { return "NewPooledTransactionHashes" }
-func (*NewPooledTransactionHashesPacket68) Kind() byte { return NewPooledTransactionHashesMsg }
+func (*NewPooledTransactionHashesPacket) Name() string { return "NewPooledTransactionHashes" }
+func (*NewPooledTransactionHashesPacket) Kind() byte { return NewPooledTransactionHashesMsg }
func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" }
func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg }
diff --git a/eth/protocols/snap/gentrie.go b/eth/protocols/snap/gentrie.go
new file mode 100644
index 0000000000..8ef1a00753
--- /dev/null
+++ b/eth/protocols/snap/gentrie.go
@@ -0,0 +1,287 @@
+// Copyright 2024 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 snap
+
+import (
+ "bytes"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/trie"
+)
+
+// genTrie interface is used by the snap syncer to generate merkle tree nodes
+// based on a received batch of states.
+type genTrie interface {
+ // update inserts the state item into generator trie.
+ update(key, value []byte) error
+
+ // commit flushes the right boundary nodes if complete flag is true. This
+ // function must be called before flushing the associated database batch.
+ commit(complete bool) common.Hash
+}
+
+// pathTrie is a wrapper over the stackTrie, incorporating numerous additional
+// logics to handle the semi-completed trie and potential leftover dangling
+// nodes in the database. It is utilized for constructing the merkle tree nodes
+// in path mode during the snap sync process.
+type pathTrie struct {
+ owner common.Hash // identifier of trie owner, empty for account trie
+ tr *trie.StackTrie // underlying raw stack trie
+ first []byte // the path of first committed node by stackTrie
+ last []byte // the path of last committed node by stackTrie
+
+ // This flag indicates whether nodes on the left boundary are skipped for
+ // committing. If set, the left boundary nodes are considered incomplete
+ // due to potentially missing left children.
+ skipLeftBoundary bool
+ db ethdb.KeyValueReader
+ batch ethdb.Batch
+}
+
+// newPathTrie initializes the path trie.
+func newPathTrie(owner common.Hash, skipLeftBoundary bool, db ethdb.KeyValueReader, batch ethdb.Batch) *pathTrie {
+ tr := &pathTrie{
+ owner: owner,
+ skipLeftBoundary: skipLeftBoundary,
+ db: db,
+ batch: batch,
+ }
+ tr.tr = trie.NewStackTrie(tr.onTrieNode)
+ return tr
+}
+
+// onTrieNode is invoked whenever a new node is committed by the stackTrie.
+//
+// As the committed nodes might be incomplete if they are on the boundaries
+// (left or right), this function has the ability to detect the incomplete
+// ones and filter them out for committing.
+//
+// Additionally, the assumption is made that there may exist leftover dangling
+// nodes in the database. This function has the ability to detect the dangling
+// nodes that fall within the path space of committed nodes (specifically on
+// the path covered by internal extension nodes) and remove them from the
+// database. This property ensures that the entire path space is uniquely
+// occupied by committed nodes.
+//
+// Furthermore, all leftover dangling nodes along the path from committed nodes
+// to the trie root (left and right boundaries) should be removed as well;
+// otherwise, they might potentially disrupt the state healing process.
+func (t *pathTrie) onTrieNode(path []byte, hash common.Hash, blob []byte) {
+ // Filter out the nodes on the left boundary if skipLeftBoundary is
+ // configured. Nodes are considered to be on the left boundary if
+ // it's the first one to be committed, or the parent/ancestor of the
+ // first committed node.
+ if t.skipLeftBoundary && (t.first == nil || bytes.HasPrefix(t.first, path)) {
+ if t.first == nil {
+ // Memorize the path of first committed node, which is regarded
+ // as left boundary. Deep-copy is necessary as the path given
+ // is volatile.
+ t.first = append([]byte{}, path...)
+
+ // The left boundary can be uniquely determined by the first committed node
+ // from stackTrie (e.g., N_1), as the shared path prefix between the first
+ // two inserted state items is deterministic (the path of N_3). The path
+ // from trie root towards the first committed node is considered the left
+ // boundary. The potential leftover dangling nodes on left boundary should
+ // be cleaned out.
+ //
+ // +-----+
+ // | N_3 | shared path prefix of state_1 and state_2
+ // +-----+
+ // /- -\
+ // +-----+ +-----+
+ // First committed node | N_1 | | N_2 | latest inserted node (contain state_2)
+ // +-----+ +-----+
+ //
+ // The node with the path of the first committed one (e.g, N_1) is not
+ // removed because it's a sibling of the nodes we want to commit, not
+ // the parent or ancestor.
+ for i := 0; i < len(path); i++ {
+ t.delete(path[:i], false)
+ }
+ }
+ return
+ }
+ // If boundary filtering is not configured, or the node is not on the left
+ // boundary, commit it to database.
+ //
+ // Note: If the current committed node is an extension node, then the nodes
+ // falling within the path between itself and its standalone (not embedded
+ // in parent) child should be cleaned out for exclusively occupy the inner
+ // path.
+ //
+ // This is essential in snap sync to avoid leaving dangling nodes within
+ // this range covered by extension node which could potentially break the
+ // state healing.
+ //
+ // The extension node is detected if its path is the prefix of last committed
+ // one and path gap is larger than one. If the path gap is only one byte,
+ // the current node could either be a full node, or a extension with single
+ // byte key. In either case, no gaps will be left in the path.
+ if t.last != nil && bytes.HasPrefix(t.last, path) && len(t.last)-len(path) > 1 {
+ for i := len(path) + 1; i < len(t.last); i++ {
+ t.delete(t.last[:i], true)
+ }
+ }
+ t.write(path, blob)
+
+ // Update the last flag. Deep-copy is necessary as the provided path is volatile.
+ if t.last == nil {
+ t.last = append([]byte{}, path...)
+ } else {
+ t.last = append(t.last[:0], path...)
+ }
+}
+
+// write commits the node write to provided database batch in path mode.
+func (t *pathTrie) write(path []byte, blob []byte) {
+ if t.owner == (common.Hash{}) {
+ rawdb.WriteAccountTrieNode(t.batch, path, blob)
+ } else {
+ rawdb.WriteStorageTrieNode(t.batch, t.owner, path, blob)
+ }
+}
+
+func (t *pathTrie) deleteAccountNode(path []byte, inner bool) {
+ if inner {
+ accountInnerLookupGauge.Inc(1)
+ } else {
+ accountOuterLookupGauge.Inc(1)
+ }
+ if !rawdb.ExistsAccountTrieNode(t.db, path) {
+ return
+ }
+ if inner {
+ accountInnerDeleteGauge.Inc(1)
+ } else {
+ accountOuterDeleteGauge.Inc(1)
+ }
+ rawdb.DeleteAccountTrieNode(t.batch, path)
+}
+
+func (t *pathTrie) deleteStorageNode(path []byte, inner bool) {
+ if inner {
+ storageInnerLookupGauge.Inc(1)
+ } else {
+ storageOuterLookupGauge.Inc(1)
+ }
+ if !rawdb.ExistsStorageTrieNode(t.db, t.owner, path) {
+ return
+ }
+ if inner {
+ storageInnerDeleteGauge.Inc(1)
+ } else {
+ storageOuterDeleteGauge.Inc(1)
+ }
+ rawdb.DeleteStorageTrieNode(t.batch, t.owner, path)
+}
+
+// delete commits the node deletion to provided database batch in path mode.
+func (t *pathTrie) delete(path []byte, inner bool) {
+ if t.owner == (common.Hash{}) {
+ t.deleteAccountNode(path, inner)
+ } else {
+ t.deleteStorageNode(path, inner)
+ }
+}
+
+// update implements genTrie interface, inserting a (key, value) pair into the
+// stack trie.
+func (t *pathTrie) update(key, value []byte) error {
+ return t.tr.Update(key, value)
+}
+
+// commit implements genTrie interface, flushing the right boundary if it's
+// considered as complete. Otherwise, the nodes on the right boundary are
+// discarded and cleaned up.
+//
+// Note, this function must be called before flushing database batch, otherwise,
+// dangling nodes might be left in database.
+func (t *pathTrie) commit(complete bool) common.Hash {
+ // If the right boundary is claimed as complete, flush them out.
+ // The nodes on both left and right boundary will still be filtered
+ // out if left boundary filtering is configured.
+ if complete {
+ // Commit all inserted but not yet committed nodes(on the right
+ // boundary) in the stackTrie.
+ hash := t.tr.Hash()
+ if t.skipLeftBoundary {
+ return common.Hash{} // hash is meaningless if left side is incomplete
+ }
+ return hash
+ }
+ // Discard nodes on the right boundary as it's claimed as incomplete. These
+ // nodes might be incomplete due to missing children on the right side.
+ // Furthermore, the potential leftover nodes on right boundary should also
+ // be cleaned out.
+ //
+ // The right boundary can be uniquely determined by the last committed node
+ // from stackTrie (e.g., N_1), as the shared path prefix between the last
+ // two inserted state items is deterministic (the path of N_3). The path
+ // from trie root towards the last committed node is considered the right
+ // boundary (root to N_3).
+ //
+ // +-----+
+ // | N_3 | shared path prefix of last two states
+ // +-----+
+ // /- -\
+ // +-----+ +-----+
+ // Last committed node | N_1 | | N_2 | latest inserted node (contain last state)
+ // +-----+ +-----+
+ //
+ // Another interesting scenario occurs when the trie is committed due to
+ // too many items being accumulated in the batch. To flush them out to
+ // the database, the path of the last inserted node (N_2) is temporarily
+ // treated as an incomplete right boundary, and nodes on this path are
+ // removed (e.g. from root to N_3).
+ // However, this path will be reclaimed as an internal path by inserting
+ // more items after the batch flush. New nodes on this path can be committed
+ // with no issues as they are actually complete. Also, from a database
+ // perspective, first deleting and then rewriting is a valid data update.
+ for i := 0; i < len(t.last); i++ {
+ t.delete(t.last[:i], false)
+ }
+ return common.Hash{} // the hash is meaningless for incomplete commit
+}
+
+// hashTrie is a wrapper over the stackTrie for implementing genTrie interface.
+type hashTrie struct {
+ tr *trie.StackTrie
+}
+
+// newHashTrie initializes the hash trie.
+func newHashTrie(batch ethdb.Batch) *hashTrie {
+ return &hashTrie{tr: trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ rawdb.WriteLegacyTrieNode(batch, hash, blob)
+ })}
+}
+
+// update implements genTrie interface, inserting a (key, value) pair into
+// the stack trie.
+func (t *hashTrie) update(key, value []byte) error {
+ return t.tr.Update(key, value)
+}
+
+// commit implements genTrie interface, committing the nodes on right boundary.
+func (t *hashTrie) commit(complete bool) common.Hash {
+ if !complete {
+ return common.Hash{} // the hash is meaningless for incomplete commit
+ }
+ return t.tr.Hash() // return hash only if it's claimed as complete
+}
diff --git a/eth/protocols/snap/gentrie_test.go b/eth/protocols/snap/gentrie_test.go
new file mode 100644
index 0000000000..1fb2dbce75
--- /dev/null
+++ b/eth/protocols/snap/gentrie_test.go
@@ -0,0 +1,553 @@
+// Copyright 2024 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 snap
+
+import (
+ "bytes"
+ "math/rand"
+ "slices"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/internal/testrand"
+ "github.com/ethereum/go-ethereum/trie"
+)
+
+type replayer struct {
+ paths []string // sort in fifo order
+ hashes []common.Hash // empty for deletion
+ unknowns int // counter for unknown write
+}
+
+func newBatchReplay() *replayer {
+ return &replayer{}
+}
+
+func (r *replayer) decode(key []byte, value []byte) {
+ account := rawdb.IsAccountTrieNode(key)
+ storage := rawdb.IsStorageTrieNode(key)
+ if !account && !storage {
+ r.unknowns += 1
+ return
+ }
+ var path []byte
+ if account {
+ _, path = rawdb.ResolveAccountTrieNodeKey(key)
+ } else {
+ _, owner, inner := rawdb.ResolveStorageTrieNode(key)
+ path = append(owner.Bytes(), inner...)
+ }
+ r.paths = append(r.paths, string(path))
+
+ if len(value) == 0 {
+ r.hashes = append(r.hashes, common.Hash{})
+ } else {
+ r.hashes = append(r.hashes, crypto.Keccak256Hash(value))
+ }
+}
+
+// updates returns a set of effective mutations. Multiple mutations targeting
+// the same node path will be merged in FIFO order.
+func (r *replayer) modifies() map[string]common.Hash {
+ set := make(map[string]common.Hash)
+ for i, path := range r.paths {
+ set[path] = r.hashes[i]
+ }
+ return set
+}
+
+// updates returns the number of updates.
+func (r *replayer) updates() int {
+ var count int
+ for _, hash := range r.modifies() {
+ if hash == (common.Hash{}) {
+ continue
+ }
+ count++
+ }
+ return count
+}
+
+// Put inserts the given value into the key-value data store.
+func (r *replayer) Put(key []byte, value []byte) error {
+ r.decode(key, value)
+ return nil
+}
+
+// Delete removes the key from the key-value data store.
+func (r *replayer) Delete(key []byte) error {
+ r.decode(key, nil)
+ return nil
+}
+
+func byteToHex(str []byte) []byte {
+ l := len(str) * 2
+ var nibbles = make([]byte, l)
+ for i, b := range str {
+ nibbles[i*2] = b / 16
+ nibbles[i*2+1] = b % 16
+ }
+ return nibbles
+}
+
+// innerNodes returns the internal nodes narrowed by two boundaries along with
+// the leftmost and rightmost sub-trie roots.
+func innerNodes(first, last []byte, includeLeft, includeRight bool, nodes map[string]common.Hash, t *testing.T) (map[string]common.Hash, []byte, []byte) {
+ var (
+ leftRoot []byte
+ rightRoot []byte
+ firstHex = byteToHex(first)
+ lastHex = byteToHex(last)
+ inner = make(map[string]common.Hash)
+ )
+ for path, hash := range nodes {
+ if hash == (common.Hash{}) {
+ t.Fatalf("Unexpected deletion, %v", []byte(path))
+ }
+ // Filter out the siblings on the left side or the left boundary nodes.
+ if !includeLeft && (bytes.Compare(firstHex, []byte(path)) > 0 || bytes.HasPrefix(firstHex, []byte(path))) {
+ continue
+ }
+ // Filter out the siblings on the right side or the right boundary nodes.
+ if !includeRight && (bytes.Compare(lastHex, []byte(path)) < 0 || bytes.HasPrefix(lastHex, []byte(path))) {
+ continue
+ }
+ inner[path] = hash
+
+ // Track the path of the leftmost sub trie root
+ if leftRoot == nil || bytes.Compare(leftRoot, []byte(path)) > 0 {
+ leftRoot = []byte(path)
+ }
+ // Track the path of the rightmost sub trie root
+ if rightRoot == nil ||
+ (bytes.Compare(rightRoot, []byte(path)) < 0) ||
+ (bytes.Compare(rightRoot, []byte(path)) > 0 && bytes.HasPrefix(rightRoot, []byte(path))) {
+ rightRoot = []byte(path)
+ }
+ }
+ return inner, leftRoot, rightRoot
+}
+
+func buildPartial(owner common.Hash, db ethdb.KeyValueReader, batch ethdb.Batch, entries []*kv, first, last int) *replayer {
+ tr := newPathTrie(owner, first != 0, db, batch)
+ for i := first; i <= last; i++ {
+ tr.update(entries[i].k, entries[i].v)
+ }
+ tr.commit(last == len(entries)-1)
+
+ replay := newBatchReplay()
+ batch.Replay(replay)
+
+ return replay
+}
+
+// TestPartialGentree verifies if the trie constructed with partial states can
+// generate consistent trie nodes that match those of the full trie.
+func TestPartialGentree(t *testing.T) {
+ for round := 0; round < 100; round++ {
+ var (
+ n = rand.Intn(1024) + 10
+ entries []*kv
+ )
+ for i := 0; i < n; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ check := func(first, last int) {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ )
+ // Build the partial tree with specific boundaries
+ r := buildPartial(common.Hash{}, db, batch, entries, first, last)
+ if r.unknowns > 0 {
+ t.Fatalf("Unknown database write: %d", r.unknowns)
+ }
+
+ // Ensure all the internal nodes are produced
+ var (
+ set = r.modifies()
+ inner, _, _ = innerNodes(entries[first].k, entries[last].k, first == 0, last == len(entries)-1, nodes, t)
+ )
+ for path, hash := range inner {
+ if _, ok := set[path]; !ok {
+ t.Fatalf("Missing nodes %v", []byte(path))
+ }
+ if hash != set[path] {
+ t.Fatalf("Inconsistent node, want %x, got: %x", hash, set[path])
+ }
+ }
+ if r.updates() != len(inner) {
+ t.Fatalf("Unexpected node write detected, want: %d, got: %d", len(inner), r.updates())
+ }
+ }
+ for j := 0; j < 100; j++ {
+ var (
+ first int
+ last int
+ )
+ for {
+ first = rand.Intn(len(entries))
+ last = rand.Intn(len(entries))
+ if first <= last {
+ break
+ }
+ }
+ check(first, last)
+ }
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {2, len(entries) - 1}, // no left
+ {2, len(entries) - 2}, // no left and right
+ {2, len(entries) - 2}, // no left and right
+ {len(entries) / 2, len(entries) / 2}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ check(c.first, c.last)
+ }
+ }
+}
+
+// TestGentreeDanglingClearing tests if the dangling nodes falling within the
+// path space of constructed tree can be correctly removed.
+func TestGentreeDanglingClearing(t *testing.T) {
+ for round := 0; round < 100; round++ {
+ var (
+ n = rand.Intn(1024) + 10
+ entries []*kv
+ )
+ for i := 0; i < n; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ check := func(first, last int) {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ )
+ // Write the junk nodes as the dangling
+ var injects []string
+ for path := range nodes {
+ for i := 0; i < len(path); i++ {
+ _, ok := nodes[path[:i]]
+ if ok {
+ continue
+ }
+ injects = append(injects, path[:i])
+ }
+ }
+ if len(injects) == 0 {
+ return
+ }
+ for _, path := range injects {
+ rawdb.WriteAccountTrieNode(db, []byte(path), testrand.Bytes(32))
+ }
+
+ // Build the partial tree with specific range
+ replay := buildPartial(common.Hash{}, db, batch, entries, first, last)
+ if replay.unknowns > 0 {
+ t.Fatalf("Unknown database write: %d", replay.unknowns)
+ }
+ set := replay.modifies()
+
+ // Make sure the injected junks falling within the path space of
+ // committed trie nodes are correctly deleted.
+ _, leftRoot, rightRoot := innerNodes(entries[first].k, entries[last].k, first == 0, last == len(entries)-1, nodes, t)
+ for _, path := range injects {
+ if bytes.Compare([]byte(path), leftRoot) < 0 && !bytes.HasPrefix(leftRoot, []byte(path)) {
+ continue
+ }
+ if bytes.Compare([]byte(path), rightRoot) > 0 {
+ continue
+ }
+ if hash, ok := set[path]; !ok || hash != (common.Hash{}) {
+ t.Fatalf("Missing delete, %v", []byte(path))
+ }
+ }
+ }
+ for j := 0; j < 100; j++ {
+ var (
+ first int
+ last int
+ )
+ for {
+ first = rand.Intn(len(entries))
+ last = rand.Intn(len(entries))
+ if first <= last {
+ break
+ }
+ }
+ check(first, last)
+ }
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {2, len(entries) - 1}, // no left
+ {2, len(entries) - 2}, // no left and right
+ {2, len(entries) - 2}, // no left and right
+ {len(entries) / 2, len(entries) / 2}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ check(c.first, c.last)
+ }
+ }
+}
+
+// TestFlushPartialTree tests the gentrie can produce complete inner trie nodes
+// even with lots of batch flushes.
+func TestFlushPartialTree(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {10, len(entries) - 1}, // no left
+ {10, len(entries) - 2}, // no left and right
+ {10, len(entries) - 10}, // no left and right
+ {11, 11}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ combined = db.NewBatch()
+ )
+ inner, _, _ := innerNodes(entries[c.first].k, entries[c.last].k, c.first == 0, c.last == len(entries)-1, nodes, t)
+
+ tr := newPathTrie(common.Hash{}, c.first != 0, db, batch)
+ for i := c.first; i <= c.last; i++ {
+ tr.update(entries[i].k, entries[i].v)
+ if rand.Intn(2) == 0 {
+ tr.commit(false)
+
+ batch.Replay(combined)
+ batch.Write()
+ batch.Reset()
+ }
+ }
+ tr.commit(c.last == len(entries)-1)
+
+ batch.Replay(combined)
+ batch.Write()
+ batch.Reset()
+
+ r := newBatchReplay()
+ combined.Replay(r)
+
+ // Ensure all the internal nodes are produced
+ set := r.modifies()
+ for path, hash := range inner {
+ if _, ok := set[path]; !ok {
+ t.Fatalf("Missing nodes %v", []byte(path))
+ }
+ if hash != set[path] {
+ t.Fatalf("Inconsistent node, want %x, got: %x", hash, set[path])
+ }
+ }
+ if r.updates() != len(inner) {
+ t.Fatalf("Unexpected node write detected, want: %d, got: %d", len(inner), r.updates())
+ }
+ }
+}
+
+// TestBoundSplit ensures two consecutive trie chunks are not overlapped with
+// each other.
+func TestBoundSplit(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ for j := 0; j < 100; j++ {
+ var (
+ next int
+ last int
+ db = rawdb.NewMemoryDatabase()
+
+ lastRightRoot []byte
+ )
+ for {
+ if next == len(entries) {
+ break
+ }
+ last = rand.Intn(len(entries)-next) + next
+
+ r := buildPartial(common.Hash{}, db, db.NewBatch(), entries, next, last)
+ set := r.modifies()
+
+ // Skip if the chunk is zero-size
+ if r.updates() == 0 {
+ next = last + 1
+ continue
+ }
+
+ // Ensure the updates in two consecutive chunks are not overlapped.
+ // The only overlapping part should be deletion.
+ if lastRightRoot != nil && len(set) > 0 {
+ // Derive the path of left-most node in this chunk
+ var leftRoot []byte
+ for path, hash := range r.modifies() {
+ if hash == (common.Hash{}) {
+ t.Fatalf("Unexpected deletion %v", []byte(path))
+ }
+ if leftRoot == nil || bytes.Compare(leftRoot, []byte(path)) > 0 {
+ leftRoot = []byte(path)
+ }
+ }
+ if bytes.HasPrefix(lastRightRoot, leftRoot) || bytes.HasPrefix(leftRoot, lastRightRoot) {
+ t.Fatalf("Two chunks are not correctly separated, lastRight: %v, left: %v", lastRightRoot, leftRoot)
+ }
+ }
+
+ // Track the updates as the last chunk
+ var rightRoot []byte
+ for path := range set {
+ if rightRoot == nil ||
+ (bytes.Compare(rightRoot, []byte(path)) < 0) ||
+ (bytes.Compare(rightRoot, []byte(path)) > 0 && bytes.HasPrefix(rightRoot, []byte(path))) {
+ rightRoot = []byte(path)
+ }
+ }
+ lastRightRoot = rightRoot
+ next = last + 1
+ }
+ }
+}
+
+// TestTinyPartialTree tests if the partial tree is too tiny(has less than two
+// states), then nothing should be committed.
+func TestTinyPartialTree(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ for i := 0; i < len(entries); i++ {
+ next := i
+ last := i + 1
+ if last >= len(entries) {
+ last = len(entries) - 1
+ }
+ db := rawdb.NewMemoryDatabase()
+ r := buildPartial(common.Hash{}, db, db.NewBatch(), entries, next, last)
+
+ if next != 0 && last != len(entries)-1 {
+ if r.updates() != 0 {
+ t.Fatalf("Unexpected data writes, got: %d", r.updates())
+ }
+ }
+ }
+}
diff --git a/eth/protocols/snap/handler_fuzzing_test.go b/eth/protocols/snap/handler_fuzzing_test.go
index cec185075d..b40cb8b971 100644
--- a/eth/protocols/snap/handler_fuzzing_test.go
+++ b/eth/protocols/snap/handler_fuzzing_test.go
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -89,7 +90,7 @@ func doFuzz(input []byte, obj interface{}, code int) {
var trieRoot common.Hash
func getChain() *core.BlockChain {
- ga := make(core.GenesisAlloc, 1000)
+ ga := make(types.GenesisAlloc, 1000)
var a = make([]byte, 20)
@@ -111,7 +112,7 @@ func getChain() *core.BlockChain {
for i := 0; i < 1000; i++ {
binary.LittleEndian.PutUint64(a, uint64(i+0xff))
- acc := core.GenesisAccount{Balance: big.NewInt(int64(i))}
+ acc := types.Account{Balance: big.NewInt(int64(i))}
if i%2 == 1 {
acc.Storage = storage
}
diff --git a/eth/protocols/snap/metrics.go b/eth/protocols/snap/metrics.go
index a7d071953f..25dbcc6386 100644
--- a/eth/protocols/snap/metrics.go
+++ b/eth/protocols/snap/metrics.go
@@ -27,21 +27,28 @@ var (
IngressRegistrationErrorMeter = metrics.NewRegisteredMeter(ingressRegistrationErrorName, nil)
EgressRegistrationErrorMeter = metrics.NewRegisteredMeter(egressRegistrationErrorName, nil)
- // deletionGauge is the metric to track how many trie node deletions
- // are performed in total during the sync process.
- deletionGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete", nil)
+ // accountInnerDeleteGauge is the metric to track how many dangling trie nodes
+ // covered by extension node in account trie are deleted during the sync.
+ accountInnerDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/account/inner", nil)
+
+ // storageInnerDeleteGauge is the metric to track how many dangling trie nodes
+ // covered by extension node in storage trie are deleted during the sync.
+ storageInnerDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/storage/inner", nil)
+
+ // accountOuterDeleteGauge is the metric to track how many dangling trie nodes
+ // above the committed nodes in account trie are deleted during the sync.
+ accountOuterDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/account/outer", nil)
+
+ // storageOuterDeleteGauge is the metric to track how many dangling trie nodes
+ // above the committed nodes in storage trie are deleted during the sync.
+ storageOuterDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/storage/outer", nil)
// lookupGauge is the metric to track how many trie node lookups are
// performed to determine if node needs to be deleted.
- lookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/lookup", nil)
-
- // boundaryAccountNodesGauge is the metric to track how many boundary trie
- // nodes in account trie are met.
- boundaryAccountNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/account", nil)
-
- // boundaryAccountNodesGauge is the metric to track how many boundary trie
- // nodes in storage tries are met.
- boundaryStorageNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/storage", nil)
+ accountInnerLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/account/lookup/inner", nil)
+ accountOuterLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/account/lookup/outer", nil)
+ storageInnerLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/lookup/inner", nil)
+ storageOuterLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/lookup/outer", nil)
// smallStorageGauge is the metric to track how many storages are small enough
// to retrieved in one or two request.
@@ -54,4 +61,9 @@ var (
// skipStorageHealingGauge is the metric to track how many storages are retrieved
// in multiple requests but healing is not necessary.
skipStorageHealingGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/noheal", nil)
+
+ // largeStorageDiscardGauge is the metric to track how many chunked storages are
+ // discarded during the snap sync.
+ largeStorageDiscardGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/discard", nil)
+ largeStorageResumedGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/resume", nil)
)
diff --git a/eth/protocols/snap/peer.go b/eth/protocols/snap/peer.go
index 3e397c0f92..d336c34a58 100644
--- a/eth/protocols/snap/peer.go
+++ b/eth/protocols/snap/peer.go
@@ -33,7 +33,7 @@ type Peer struct {
logger log.Logger // Contextual logger with the peer id injected
}
-// NewPeer create a wrapper for a network connection and negotiated protocol
+// NewPeer creates a wrapper for a network connection and negotiated protocol
// version.
func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
id := p.ID().String()
@@ -47,7 +47,7 @@ func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
}
}
-// NewFakePeer create a fake snap peer without a backing p2p peer, for testing purposes.
+// NewFakePeer creates a fake snap peer without a backing p2p peer, for testing purposes.
func NewFakePeer(version uint, id string, rw p2p.MsgReadWriter) *Peer {
return &Peer{
id: id,
diff --git a/eth/protocols/snap/progress_test.go b/eth/protocols/snap/progress_test.go
new file mode 100644
index 0000000000..9d923bd2f5
--- /dev/null
+++ b/eth/protocols/snap/progress_test.go
@@ -0,0 +1,154 @@
+// Copyright 2024 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 snap
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Legacy sync progress definitions
+type legacyStorageTask struct {
+ Next common.Hash // Next account to sync in this interval
+ Last common.Hash // Last account to sync in this interval
+}
+
+type legacyAccountTask struct {
+ Next common.Hash // Next account to sync in this interval
+ Last common.Hash // Last account to sync in this interval
+ SubTasks map[common.Hash][]*legacyStorageTask // Storage intervals needing fetching for large contracts
+}
+
+type legacyProgress struct {
+ Tasks []*legacyAccountTask // The suspended account tasks (contract tasks within)
+}
+
+func compareProgress(a legacyProgress, b SyncProgress) bool {
+ if len(a.Tasks) != len(b.Tasks) {
+ return false
+ }
+ for i := 0; i < len(a.Tasks); i++ {
+ if a.Tasks[i].Next != b.Tasks[i].Next {
+ return false
+ }
+ if a.Tasks[i].Last != b.Tasks[i].Last {
+ return false
+ }
+ // new fields are not checked here
+
+ if len(a.Tasks[i].SubTasks) != len(b.Tasks[i].SubTasks) {
+ return false
+ }
+ for addrHash, subTasksA := range a.Tasks[i].SubTasks {
+ subTasksB, ok := b.Tasks[i].SubTasks[addrHash]
+ if !ok || len(subTasksB) != len(subTasksA) {
+ return false
+ }
+ for j := 0; j < len(subTasksA); j++ {
+ if subTasksA[j].Next != subTasksB[j].Next {
+ return false
+ }
+ if subTasksA[j].Last != subTasksB[j].Last {
+ return false
+ }
+ }
+ }
+ }
+ return true
+}
+
+func makeLegacyProgress() legacyProgress {
+ return legacyProgress{
+ Tasks: []*legacyAccountTask{
+ {
+ Next: common.Hash{},
+ Last: common.Hash{0x77},
+ SubTasks: map[common.Hash][]*legacyStorageTask{
+ common.Hash{0x1}: {
+ {
+ Next: common.Hash{},
+ Last: common.Hash{0xff},
+ },
+ },
+ },
+ },
+ {
+ Next: common.Hash{0x88},
+ Last: common.Hash{0xff},
+ },
+ },
+ }
+}
+
+func convertLegacy(legacy legacyProgress) SyncProgress {
+ var progress SyncProgress
+ for i, task := range legacy.Tasks {
+ subTasks := make(map[common.Hash][]*storageTask)
+ for owner, list := range task.SubTasks {
+ var cpy []*storageTask
+ for i := 0; i < len(list); i++ {
+ cpy = append(cpy, &storageTask{
+ Next: list[i].Next,
+ Last: list[i].Last,
+ })
+ }
+ subTasks[owner] = cpy
+ }
+ accountTask := &accountTask{
+ Next: task.Next,
+ Last: task.Last,
+ SubTasks: subTasks,
+ }
+ if i == 0 {
+ accountTask.StorageCompleted = []common.Hash{{0xaa}, {0xbb}} // fulfill new fields
+ }
+ progress.Tasks = append(progress.Tasks, accountTask)
+ }
+ return progress
+}
+
+func TestSyncProgressCompatibility(t *testing.T) {
+ // Decode serialized bytes of legacy progress, backward compatibility
+ legacy := makeLegacyProgress()
+ blob, err := json.Marshal(legacy)
+ if err != nil {
+ t.Fatalf("Failed to marshal progress %v", err)
+ }
+ var dec SyncProgress
+ if err := json.Unmarshal(blob, &dec); err != nil {
+ t.Fatalf("Failed to unmarshal progress %v", err)
+ }
+ if !compareProgress(legacy, dec) {
+ t.Fatal("sync progress is not backward compatible")
+ }
+
+ // Decode serialized bytes of new format progress
+ progress := convertLegacy(legacy)
+ blob, err = json.Marshal(progress)
+ if err != nil {
+ t.Fatalf("Failed to marshal progress %v", err)
+ }
+ var legacyDec legacyProgress
+ if err := json.Unmarshal(blob, &legacyDec); err != nil {
+ t.Fatalf("Failed to unmarshal progress %v", err)
+ }
+ if !compareProgress(legacyDec, progress) {
+ t.Fatal("sync progress is not forward compatible")
+ }
+}
diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go
index d3b27b7c66..d5545b34c4 100644
--- a/eth/protocols/snap/sync.go
+++ b/eth/protocols/snap/sync.go
@@ -95,6 +95,9 @@ const (
// trienodeHealThrottleDecrease is the divisor for the throttle when the
// rate of arriving data is lower than the rate of processing it.
trienodeHealThrottleDecrease = 1.25
+
+ // batchSizeThreshold is the maximum size allowed for gentrie batch.
+ batchSizeThreshold = 8 * 1024 * 1024
)
var (
@@ -296,11 +299,19 @@ type bytecodeHealResponse struct {
// accountTask represents the sync task for a chunk of the account snapshot.
type accountTask struct {
- // These fields get serialized to leveldb on shutdown
+ // These fields get serialized to key-value store on shutdown
Next common.Hash // Next account to sync in this interval
Last common.Hash // Last account to sync in this interval
SubTasks map[common.Hash][]*storageTask // Storage intervals needing fetching for large contracts
+ // This is a list of account hashes whose storage are already completed
+ // in this cycle. This field is newly introduced in v1.14 and will be
+ // empty if the task is resolved from legacy progress data. Furthermore,
+ // this additional field will be ignored by legacy Geth. The only side
+ // effect is that these contracts might be resynced in the new cycle,
+ // retaining the legacy behavior.
+ StorageCompleted []common.Hash `json:",omitempty"`
+
// These fields are internals used during runtime
req *accountRequest // Pending request to fill this task
res *accountResponse // Validate response filling this task
@@ -310,15 +321,40 @@ type accountTask struct {
needState []bool // Flags whether the filling accounts need storage retrieval
needHeal []bool // Flags whether the filling accounts's state was chunked and need healing
- codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
- stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
+ codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
+ stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
+ stateCompleted map[common.Hash]struct{} // Account hashes whose storage have been completed
- genBatch ethdb.Batch // Batch used by the node generator
- genTrie *trie.StackTrie // Node generator from storage slots
+ genBatch ethdb.Batch // Batch used by the node generator
+ genTrie genTrie // Node generator from storage slots
done bool // Flag whether the task can be removed
}
+// activeSubTasks returns the set of storage tasks covered by the current account
+// range. Normally this would be the entire subTask set, but on a sync interrupt
+// and later resume it can happen that a shorter account range is retrieved. This
+// method ensures that we only start up the subtasks covered by the latest account
+// response.
+//
+// Nil is returned if the account range is empty.
+func (task *accountTask) activeSubTasks() map[common.Hash][]*storageTask {
+ if len(task.res.hashes) == 0 {
+ return nil
+ }
+ var (
+ tasks = make(map[common.Hash][]*storageTask)
+ last = task.res.hashes[len(task.res.hashes)-1]
+ )
+ for hash, subTasks := range task.SubTasks {
+ subTasks := subTasks // closure
+ if hash.Cmp(last) <= 0 {
+ tasks[hash] = subTasks
+ }
+ }
+ return tasks
+}
+
// storageTask represents the sync task for a chunk of the storage snapshot.
type storageTask struct {
Next common.Hash // Next account to sync in this interval
@@ -328,8 +364,8 @@ type storageTask struct {
root common.Hash // Storage root hash for this instance
req *storageRequest // Pending request to fill this task
- genBatch ethdb.Batch // Batch used by the node generator
- genTrie *trie.StackTrie // Node generator from storage slots
+ genBatch ethdb.Batch // Batch used by the node generator
+ genTrie genTrie // Node generator from storage slots
done bool // Flag whether the task can be removed
}
@@ -730,19 +766,6 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
}
}
-// cleanPath is used to remove the dangling nodes in the stackTrie.
-func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) {
- if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db, path) {
- rawdb.DeleteAccountTrieNode(batch, path)
- deletionGauge.Inc(1)
- }
- if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db, owner, path) {
- rawdb.DeleteStorageTrieNode(batch, owner, path)
- deletionGauge.Inc(1)
- }
- lookupGauge.Inc(1)
-}
-
// loadSyncStatus retrieves a previously aborted sync status from the database,
// or generates a fresh one if none is available.
func (s *Syncer) loadSyncStatus() {
@@ -760,28 +783,27 @@ func (s *Syncer) loadSyncStatus() {
for _, task := range s.tasks {
task := task // closure for task.genBatch in the stacktrie writer callback
+ // Restore the completed storages
+ task.stateCompleted = make(map[common.Hash]struct{})
+ for _, hash := range task.StorageCompleted {
+ task.stateCompleted[hash] = struct{}{}
+ }
+ task.StorageCompleted = nil
+
+ // Allocate batch for account trie generation
task.genBatch = ethdb.HookedBatch{
Batch: s.db.NewBatch(),
OnPut: func(key []byte, value []byte) {
s.accountBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, blob, s.scheme)
- })
- if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(task.genBatch, common.Hash{}, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(task.Next != (common.Hash{}), task.Last != common.MaxHash, boundaryAccountNodesGauge)
+ if s.scheme == rawdb.HashScheme {
+ task.genTrie = newHashTrie(task.genBatch)
}
- task.genTrie = trie.NewStackTrie(options)
+ if s.scheme == rawdb.PathScheme {
+ task.genTrie = newPathTrie(common.Hash{}, task.Next != common.Hash{}, s.db, task.genBatch)
+ }
+ // Restore leftover storage tasks
for accountHash, subtasks := range task.SubTasks {
for _, subtask := range subtasks {
subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback
@@ -792,23 +814,12 @@ func (s *Syncer) loadSyncStatus() {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- owner := accountHash // local assignment for stacktrie writer closure
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, blob, s.scheme)
- })
- if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(subtask.genBatch, owner, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(subtask.Next != common.Hash{}, subtask.Last != common.MaxHash, boundaryStorageNodesGauge)
+ if s.scheme == rawdb.HashScheme {
+ subtask.genTrie = newHashTrie(subtask.genBatch)
+ }
+ if s.scheme == rawdb.PathScheme {
+ subtask.genTrie = newPathTrie(accountHash, subtask.Next != common.Hash{}, s.db, subtask.genBatch)
}
- subtask.genTrie = trie.NewStackTrie(options)
}
}
}
@@ -864,27 +875,20 @@ func (s *Syncer) loadSyncStatus() {
s.accountBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, common.Hash{}, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(next != common.Hash{}, last != common.MaxHash, boundaryAccountNodesGauge)
+ tr = newPathTrie(common.Hash{}, next != common.Hash{}, s.db, batch)
}
s.tasks = append(s.tasks, &accountTask{
- Next: next,
- Last: last,
- SubTasks: make(map[common.Hash][]*storageTask),
- genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ Next: next,
+ Last: last,
+ SubTasks: make(map[common.Hash][]*storageTask),
+ genBatch: batch,
+ stateCompleted: make(map[common.Hash]struct{}),
+ genTrie: tr,
})
log.Debug("Created account sync task", "from", next, "last", last)
@@ -896,17 +900,32 @@ func (s *Syncer) loadSyncStatus() {
func (s *Syncer) saveSyncStatus() {
// Serialize any partial progress to disk before spinning down
for _, task := range s.tasks {
+ // Claim the right boundary as incomplete before flushing the
+ // accumulated nodes in batch, the nodes on right boundary
+ // will be discarded and cleaned up by this call.
+ task.genTrie.commit(false)
if err := task.genBatch.Write(); err != nil {
log.Error("Failed to persist account slots", "err", err)
}
for _, subtasks := range task.SubTasks {
for _, subtask := range subtasks {
+ // Same for account trie, discard and cleanup the
+ // incomplete right boundary.
+ subtask.genTrie.commit(false)
if err := subtask.genBatch.Write(); err != nil {
log.Error("Failed to persist storage slots", "err", err)
}
}
}
+ // Save the account hashes of completed storage.
+ task.StorageCompleted = make([]common.Hash, 0, len(task.stateCompleted))
+ for hash := range task.stateCompleted {
+ task.StorageCompleted = append(task.StorageCompleted, hash)
+ }
+ if len(task.StorageCompleted) > 0 {
+ log.Debug("Leftover completed storages", "number", len(task.StorageCompleted), "next", task.Next, "last", task.Last)
+ }
}
// Store the actual progress markers
progress := &SyncProgress{
@@ -998,6 +1017,10 @@ func (s *Syncer) cleanStorageTasks() {
task.pend--
+ // Mark the state as complete to prevent resyncing, regardless
+ // if state healing is necessary.
+ task.stateCompleted[account] = struct{}{}
+
// If this was the last pending task, forward the account task
if task.pend == 0 {
s.forwardAccountTask(task)
@@ -1267,7 +1290,8 @@ func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *st
continue
}
// Skip tasks that are already retrieving (or done with) all small states
- if len(task.SubTasks) == 0 && len(task.stateTasks) == 0 {
+ storageTasks := task.activeSubTasks()
+ if len(storageTasks) == 0 && len(task.stateTasks) == 0 {
continue
}
// Task pending retrieval, try to find an idle peer. If no such peer
@@ -1318,8 +1342,7 @@ func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *st
roots = make([]common.Hash, 0, storageSets)
subtask *storageTask
)
-
- for account, subtasks := range task.SubTasks {
+ for account, subtasks := range storageTasks {
for _, st := range subtasks {
// Skip any subtasks already filling
if st.req != nil {
@@ -1968,11 +1991,11 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.res = res
// Ensure that the response doesn't overflow into the subsequent task
- last := res.task.Last.Big()
+ lastBig := res.task.Last.Big()
for i, hash := range res.hashes {
// Mark the range complete if the last is already included.
// Keep iteration to delete the extra states if exists.
- cmp := hash.Big().Cmp(last)
+ cmp := hash.Big().Cmp(lastBig)
if cmp == 0 {
res.cont = false
continue
@@ -2010,7 +2033,21 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
}
// Check if the account is a contract with an unknown storage trie
if account.Root != types.EmptyRootHash {
- if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
+ // If the storage was already retrieved in the last cycle, there's no need
+ // to resync it again, regardless of whether the storage root is consistent
+ // or not.
+ if _, exist := res.task.stateCompleted[res.hashes[i]]; exist {
+ // The leftover storage tasks are not expected, unless system is
+ // very wrong.
+ if _, ok := res.task.SubTasks[res.hashes[i]]; ok {
+ panic(fmt.Errorf("unexpected leftover storage tasks, owner: %x", res.hashes[i]))
+ }
+ // Mark the healing tag if storage root node is inconsistent, or
+ // it's non-existent due to storage chunking.
+ if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
+ res.task.needHeal[i] = true
+ }
+ } else {
// If there was a previous large state retrieval in progress,
// don't restart it from scratch. This happens if a sync cycle
// is interrupted and resumed later. However, *do* update the
@@ -2024,7 +2061,12 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.needHeal[i] = true
resumed[res.hashes[i]] = struct{}{}
+ largeStorageResumedGauge.Inc(1)
} else {
+ // It's possible that in the hash scheme, the storage, along
+ // with the trie nodes of the given root, is already present
+ // in the database. Schedule the storage task anyway to simplify
+ // the logic here.
res.task.stateTasks[res.hashes[i]] = account.Root
}
@@ -2033,13 +2075,29 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
}
}
}
- // Delete any subtasks that have been aborted but not resumed. This may undo
- // some progress if a new peer gives us less accounts than an old one, but for
- // now we have to live with that.
- for hash := range res.task.SubTasks {
- if _, ok := resumed[hash]; !ok {
- log.Debug("Aborting suspended storage retrieval", "account", hash)
- delete(res.task.SubTasks, hash)
+ // Delete any subtasks that have been aborted but not resumed. It's essential
+ // as the corresponding contract might be self-destructed in this cycle(it's
+ // no longer possible in ethereum as self-destruction is disabled in Cancun
+ // Fork, but the condition is still necessary for other networks).
+ //
+ // Keep the leftover storage tasks if they are not covered by the responded
+ // account range which should be picked up in next account wave.
+ if len(res.hashes) > 0 {
+ // The hash of last delivered account in the response
+ last := res.hashes[len(res.hashes)-1]
+ for hash := range res.task.SubTasks {
+ // TODO(rjl493456442) degrade the log level before merging.
+ if hash.Cmp(last) > 0 {
+ log.Info("Keeping suspended storage retrieval", "account", hash)
+ continue
+ }
+ // TODO(rjl493456442) degrade the log level before merging.
+ // It should never happen in ethereum.
+ if _, ok := resumed[hash]; !ok {
+ log.Error("Aborting suspended storage retrieval", "account", hash)
+ delete(res.task.SubTasks, hash)
+ largeStorageDiscardGauge.Inc(1)
+ }
}
}
// If the account range contained no contracts, or all have been fully filled
@@ -2145,6 +2203,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) {
res.mainTask.needState[j] = false
res.mainTask.pend--
+ res.mainTask.stateCompleted[account] = struct{}{} // mark it as completed
smallStorageGauge.Inc(1)
}
// If the last contract was chunked, mark it as needing healing
@@ -2196,25 +2255,20 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- owner := account // local assignment for stacktrie writer closure
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, owner, path)
- })
// Keep the left boundary as it's the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(false, r.End() != common.MaxHash, boundaryStorageNodesGauge)
+ tr = newPathTrie(account, false, s.db, batch)
}
tasks = append(tasks, &storageTask{
Next: common.Hash{},
Last: r.End(),
root: acc.Root,
genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ genTrie: tr,
})
for r.Next() {
@@ -2224,27 +2278,19 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, owner, path)
- })
- // Skip the left boundary as it's not the first range
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(true, r.End() != common.MaxHash, boundaryStorageNodesGauge)
+ tr = newPathTrie(account, true, s.db, batch)
}
tasks = append(tasks, &storageTask{
Next: r.Start(),
Last: r.End(),
root: acc.Root,
genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ genTrie: tr,
})
}
@@ -2293,26 +2339,18 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
if i < len(res.hashes)-1 || res.subTask == nil {
// no need to make local reassignment of account: this closure does not outlive the loop
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, account, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner only in the context of the
- // path scheme. Deletion is forbidden in the hash scheme, as it can
- // disrupt state completeness.
- //
- // Notably, boundary nodes can be also kept because the whole storage
- // trie is complete.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, account, path)
- })
+ // Keep the left boundary as it's complete
+ tr = newPathTrie(account, false, s.db, batch)
}
- tr := trie.NewStackTrie(options)
for j := 0; j < len(res.hashes[i]); j++ {
- tr.Update(res.hashes[i][j][:], res.slots[i][j])
+ tr.update(res.hashes[i][j][:], res.slots[i][j])
}
- tr.Commit()
+ tr.commit(true)
}
// Persist the received storage segments. These flat state maybe
// outdated during the sync, but it can be fixed later during the
@@ -2323,14 +2361,14 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
// If we're storing large contracts, generate the trie nodes
// on the fly to not trash the gluing points
if i == len(res.hashes)-1 && res.subTask != nil {
- res.subTask.genTrie.Update(res.hashes[i][j][:], res.slots[i][j])
+ res.subTask.genTrie.update(res.hashes[i][j][:], res.slots[i][j])
}
}
}
// Large contracts could have generated new trie nodes, flush them to disk
if res.subTask != nil {
if res.subTask.done {
- root := res.subTask.genTrie.Commit()
+ root := res.subTask.genTrie.commit(res.subTask.Last == common.MaxHash)
if err := res.subTask.genBatch.Write(); err != nil {
log.Error("Failed to persist stack slots", "err", err)
}
@@ -2347,8 +2385,8 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
}
}
}
- }
- if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize {
+ } else if res.subTask.genBatch.ValueSize() > batchSizeThreshold {
+ res.subTask.genTrie.commit(false)
if err := res.subTask.genBatch.Write(); err != nil {
log.Error("Failed to persist stack slots", "err", err)
}
@@ -2545,7 +2583,7 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
panic(err) // Really shouldn't ever happen
}
- task.genTrie.Update(hash[:], full)
+ task.genTrie.update(hash[:], full)
}
}
// Flush anything written just now and update the stats
@@ -2563,18 +2601,30 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
}
task.Next = incHash(hash)
+
+ // Remove the completion flag once the account range is pushed
+ // forward. The leftover accounts will be skipped in the next
+ // cycle.
+ delete(task.stateCompleted, hash)
}
// All accounts marked as complete, track if the entire task is done
task.done = !res.cont
+ // Error out if there is any leftover completion flag.
+ if task.done && len(task.stateCompleted) != 0 {
+ panic(fmt.Errorf("storage completion flags should be emptied, %d left", len(task.stateCompleted)))
+ }
// Stack trie could have generated trie nodes, push them to disk (we need to
// flush after finalizing task.done. It's fine even if we crash and lose this
// write as it will only cause more data to be downloaded during heal.
if task.done {
- task.genTrie.Commit()
- }
-
- if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done {
+ task.genTrie.commit(task.Last == common.MaxHash)
+ if err := task.genBatch.Write(); err != nil {
+ log.Error("Failed to persist stack account", "err", err)
+ }
+ task.genBatch.Reset()
+ } else if task.genBatch.ValueSize() > batchSizeThreshold {
+ task.genTrie.commit(false)
if err := task.genBatch.Write(); err != nil {
log.Error("Failed to persist stack account", "err", err)
}
diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go
index 0c43ff7473..1bcfd9af4e 100644
--- a/eth/protocols/snap/sync_test.go
+++ b/eth/protocols/snap/sync_test.go
@@ -36,8 +36,10 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/testutil"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
"golang.org/x/exp/slices"
)
@@ -1635,7 +1637,7 @@ func getCodeByHash(hash common.Hash) []byte {
// makeAccountTrieNoStorage spits out a trie, along with the leafs
func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
)
@@ -1643,7 +1645,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1672,7 +1674,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
entries []*kv
boundaries []common.Hash
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
)
// Initialize boundaries
@@ -1697,7 +1699,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := 0; i < len(boundaries); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0),
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(uint64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)),
})
@@ -1709,7 +1711,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1733,7 +1735,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// has a unique storage set.
func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
storageRoots = make(map[common.Hash]common.Hash)
@@ -1755,7 +1757,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
@@ -1791,7 +1793,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
// makeAccountTrieWithStorage spits out a trie, along with the leafs
func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, boundary bool, uneven bool) (*trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
storageRoots = make(map[common.Hash]common.Hash)
@@ -1826,7 +1828,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
@@ -1870,7 +1872,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
// makeStorageTrieWithSeed fills a storage trie with n items, returning the
// not-yet-committed trie and the sorted entries. The seeds can be used to ensure
// that tries are unique.
-func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
var entries []*kv
for i := uint64(1); i <= n; i++ {
@@ -1893,7 +1895,7 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Databas
// makeBoundaryStorageTrie constructs a storage trie. Instead of filling
// storage slots normally, this function will fill a few slots which have
// boundary hash.
-func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
var (
entries []*kv
boundaries []common.Hash
@@ -1945,7 +1947,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
// makeUnevenStorageTrie constructs a storage tries will states distributed in
// different range unevenly.
-func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
var (
entries []*kv
tr, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
@@ -1977,7 +1979,7 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (com
func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
t.Helper()
- triedb := trie.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme))
+ triedb := triedb.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme))
accTrie, err := trie.New(trie.StateTrieID(root), triedb)
if err != nil {
t.Fatal(err)
@@ -2124,9 +2126,9 @@ func TestSlotEstimation(t *testing.T) {
}
}
-func newDbConfig(scheme string) *trie.Config {
+func newDbConfig(scheme string) *triedb.Config {
if scheme == rawdb.HashScheme {
- return &trie.Config{}
+ return &triedb.Config{}
}
- return &trie.Config{PathDB: pathdb.Defaults}
+ return &triedb.Config{PathDB: pathdb.Defaults}
}
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index b4180ef8c3..24d24f58af 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// noopReleaser is returned in case there is no operation expected
@@ -41,7 +42,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
var (
current *types.Block
database state.Database
- triedb *trie.Database
+ tdb *triedb.Database
report = true
origin = block.NumberU64()
)
@@ -67,14 +68,14 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance.
- database = state.NewDatabaseWithConfig(eth.chainDb, trie.HashDefaults)
+ database = state.NewDatabaseWithConfig(eth.chainDb, triedb.HashDefaults)
if statedb, err = state.New(block.Root(), database, nil); err == nil {
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
return statedb, noopReleaser, nil
}
}
// The optional base statedb is given, mark the start point as parent block
- statedb, database, triedb, report = base, base.Database(), base.Database().TrieDB(), false
+ statedb, database, tdb, report = base, base.Database(), base.Database().TrieDB(), false
current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if current == nil {
@@ -88,8 +89,8 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance.
- triedb = trie.NewDatabase(eth.chainDb, trie.HashDefaults)
- database = state.NewDatabaseWithNodeDB(eth.chainDb, triedb)
+ tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
+ database = state.NewDatabaseWithNodeDB(eth.chainDb, tdb)
// If we didn't check the live database, do check state over ephemeral database,
// otherwise we would rewind past a persisted block (specific corner case is
@@ -174,19 +175,19 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
}
// Hold the state reference and also drop the parent state
// to prevent accumulating too many nodes in memory.
- triedb.Reference(root, common.Hash{})
+ tdb.Reference(root, common.Hash{})
if parent != (common.Hash{}) {
- triedb.Dereference(parent)
+ tdb.Dereference(parent)
}
parent = root
}
if report {
- _, nodes, imgs := triedb.Size() // all memory is contained within the nodes return in hashdb
+ _, nodes, imgs := tdb.Size() // all memory is contained within the nodes return in hashdb
log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs)
}
- return statedb, func() { triedb.Dereference(block.Root()) }, nil
+ return statedb, func() { tdb.Dereference(block.Root()) }, nil
}
func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) {
diff --git a/eth/sync.go b/eth/sync.go
index 44c0ff6d38..58adb291fb 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -22,7 +22,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/log"
@@ -36,7 +36,7 @@ const (
// syncTransactions starts sending all currently pending transactions to the given peer.
func (h *handler) syncTransactions(p *eth.Peer) {
var hashes []common.Hash
- for _, batch := range h.txpool.Pending(false) {
+ for _, batch := range h.txpool.Pending(txpool.PendingFilter{OnlyPlainTxs: true}) {
for _, tx := range batch {
hashes = append(hashes, tx.Hash)
}
@@ -251,24 +251,6 @@ func (cs *chainSyncer) startSync(op *chainSyncOp) {
// doSync synchronizes the local blockchain with a remote peer.
func (h *handler) doSync(op *chainSyncOp) error {
- if op.mode == downloader.SnapSync {
- // Before launch the snap sync, we have to ensure user uses the same
- // txlookup limit.
- // The main concern here is: during the snap sync Geth won't index the
- // block(generate tx indices) before the HEAD-limit. But if user changes
- // the limit in the next snap sync(e.g. user kill Geth manually and
- // restart) then it will be hard for Geth to figure out the oldest block
- // has been indexed. So here for the user-experience wise, it's non-optimal
- // that user can't change limit during the snap sync. If changed, Geth
- // will just blindly use the original one.
- limit := h.chain.TxLookupLimit()
- if stored := rawdb.ReadFastTxLookupLimit(h.database); stored == nil {
- rawdb.WriteFastTxLookupLimit(h.database, limit)
- } else if *stored != limit {
- h.chain.SetTxLookupLimit(*stored)
- log.Warn("Update txLookup limit", "provided", limit, "updated", *stored)
- }
- }
// Run the sync cycle, and disable snap sync if we're past the pivot block
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
if err != nil {
diff --git a/eth/sync_test.go b/eth/sync_test.go
index a476f6234c..e3def8029d 100644
--- a/eth/sync_test.go
+++ b/eth/sync_test.go
@@ -28,7 +28,6 @@ import (
)
// Tests that snap sync is disabled after a successful sync cycle.
-func TestSnapSyncDisabling67(t *testing.T) { testSnapSyncDisabling(t, eth.ETH67, snap.SNAP1) }
func TestSnapSyncDisabling68(t *testing.T) { testSnapSyncDisabling(t, eth.ETH68, snap.SNAP1) }
// Tests that snap sync gets disabled as soon as a real block is successfully
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 49246c61a2..04d91b9062 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -47,6 +47,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
)
const (
@@ -93,7 +94,7 @@ type Backend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
RPCGasCap() uint64
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
@@ -918,7 +919,7 @@ txloop:
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
}
} else {
- coinbaseBalance := statedb.GetBalance(blockCtx.Coinbase)
+ coinbaseBalance := big.NewInt(statedb.GetBalance(blockCtx.Coinbase).ToBig().Int64())
// nolint : contextcheck
result, err := core.ApplyMessageNoFeeBurnOrTip(vmenv, *msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
@@ -928,10 +929,10 @@ txloop:
}
if london {
- statedb.AddBalance(result.BurntContractAddress, result.FeeBurnt)
+ statedb.AddBalance(result.BurntContractAddress, uint256.NewInt(result.FeeBurnt.Uint64()))
}
- statedb.AddBalance(blockCtx.Coinbase, result.FeeTipped)
+ statedb.AddBalance(blockCtx.Coinbase, uint256.NewInt(result.FeeTipped.Uint64()))
output1 := new(big.Int).SetBytes(result.SenderInitBalance.Bytes())
output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes())
@@ -1172,10 +1173,10 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
config.BorTraceEnabled = defaultBorTraceEnabled
}
- tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
- if tx == nil {
+ found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
+ if !found {
// For BorTransaction, there will be no trace available
- tx, _, _, _ = rawdb.ReadBorTransaction(api.backend.ChainDb(), hash)
+ tx, _, _, _ := rawdb.ReadBorTransaction(api.backend.ChainDb(), hash)
if tx != nil {
return ðapi.ExecutionResult{
StructLogs: make([]ethapi.StructLogRes, 0),
@@ -1186,8 +1187,9 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
}
if err != nil {
- return nil, err
+ return nil, ethapi.NewTxIndexingError()
}
+
// It shouldn't happen in practice.
if blockNumber == 0 {
return nil, errors.New("genesis is not traceable")
@@ -1284,7 +1286,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
config.BlockOverrides.Apply(&vmctx)
}
// Execute the trace
- msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee())
+ msg, err := args.ToMessage(api.backend.RPCGasCap(), vmctx.BaseFee)
if err != nil {
return nil, err
}
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index 00c2e58e20..e5ff67d50f 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -120,9 +120,9 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
return b.chain.GetBlockByNumber(uint64(number)), nil
}
-func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
- return tx, hash, blockNumber, index, nil
+ return tx != nil, tx, hash, blockNumber, index, nil
}
func (b *testBackend) RPCGasCap() uint64 {
@@ -218,7 +218,7 @@ func TestTraceCall(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -441,7 +441,7 @@ func TestTraceTransaction(t *testing.T) {
accounts := newAccounts(2)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
},
@@ -502,7 +502,7 @@ func TestTraceBlock(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -694,7 +694,7 @@ func TestTracingWithOverrides(t *testing.T) {
storageAccount := common.Address{0x13, 37}
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -1077,7 +1077,7 @@ func TestTraceChain(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index 0f77a39996..13ca89dbfd 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -128,13 +128,9 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
- blockContext = vm.BlockContext{
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
+
+ context = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Coinbase: test.Context.Miner,
@@ -144,23 +140,22 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
GasLimit: uint64(test.Context.GasLimit),
BaseFee: test.Genesis.BaseFee,
}
- triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
)
- triedb.Close()
+ state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
+ evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
- vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background())
+ vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), nil)
if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
@@ -240,10 +235,6 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- msg, err := core.TransactionToMessage(tx, signer, nil)
- if err != nil {
- b.Fatalf("failed to prepare transaction for tracing: %v", err)
- }
origin, _ := signer.Sender(tx)
txContext := vm.TxContext{
@@ -259,8 +250,12 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
+ if err != nil {
+ b.Fatalf("failed to prepare transaction for tracing: %v", err)
+ }
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ defer state.Close()
b.ReportAllocs()
b.ResetTimer()
@@ -271,8 +266,10 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
- snap := statedb.Snapshot()
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
+
+ snap := state.StateDB.Snapshot()
+
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(context.Background()); err != nil {
@@ -283,7 +280,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatal(err)
}
- statedb.RevertToSnapshot(snap)
+ state.StateDB.RevertToSnapshot(snap)
}
}
@@ -395,18 +392,18 @@ func TestInternals(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
- core.GenesisAlloc{
- to: core.GenesisAccount{
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(),
+ types.GenesisAlloc{
+ to: types.Account{
Code: tc.code,
},
- origin: core.GenesisAccount{
+ origin: types.Account{
Balance: big.NewInt(500000000000000),
},
}, false, rawdb.HashScheme)
- defer triedb.Close()
+ defer state.Close()
- evm := vm.NewEVM(blockContext, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
msg := &core.Message{
To: &to,
From: origin,
diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go
index 57697fb2f4..f26aaeeafd 100644
--- a/eth/tracers/internal/tracetest/flat_calltrace_test.go
+++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go
@@ -91,11 +91,6 @@ func flatCallTracerTestRunner(tb testing.TB, tracerName string, filename string,
return fmt.Errorf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ := signer.Sender(tx)
- txContext := vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
blockContext := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -105,22 +100,19 @@ func flatCallTracerTestRunner(tb testing.TB, tracerName string, filename string,
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ defer state.Close()
// Create the tracer, the EVM environment and run it
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
if err != nil {
return fmt.Errorf("failed to create call tracer: %v", err)
}
-
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
}
-
+ evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(context.Background()); err != nil {
diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go
index a54b4a93e0..7cf918a42d 100644
--- a/eth/tracers/internal/tracetest/prestate_test.go
+++ b/eth/tracers/internal/tracetest/prestate_test.go
@@ -102,12 +102,8 @@ func testPrestateDiffTracer(t *testing.T, tracerName string, dirPath string) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
+
blockContext = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -118,22 +114,21 @@ func testPrestateDiffTracer(t *testing.T, tracerName string, dirPath string) {
GasLimit: uint64(test.Context.GasLimit),
BaseFee: test.Genesis.BaseFee,
}
- triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
)
- defer triedb.Close()
+ defer state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
+ evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(context.Background()); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
index 2f6e08e707..78a599a9be 100644
--- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
@@ -90,7 +90,7 @@
},
"post": {
"0x808b4da0be6c9512e948521452227efc619bea52": {
- "balance": "0x2cd72a36dd031f089",
+ "balance": "0x2cd987071ba2346b6",
"nonce": 1223933
},
"0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": {
diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go
index d3f7a79cbb..68e0b1b1c3 100644
--- a/eth/tracers/js/tracer_test.go
+++ b/eth/tracers/js/tracer_test.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type account struct{}
@@ -37,9 +38,9 @@ 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(*big.Int) {}
+func (account) SetBalance(*uint256.Int) {}
func (account) SetNonce(uint64) {}
-func (account) Balance() *big.Int { return nil }
+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) {}
@@ -48,8 +49,8 @@ type dummyStatedb struct {
state.StateDB
}
-func (*dummyStatedb) GetRefund() uint64 { return 1337 }
-func (*dummyStatedb) GetBalance(addr common.Address) *big.Int { return new(big.Int) }
+func (*dummyStatedb) GetRefund() uint64 { return 1337 }
+func (*dummyStatedb) GetBalance(addr common.Address) *uint256.Int { return new(uint256.Int) }
type vmContext struct {
blockCtx vm.BlockContext
@@ -65,7 +66,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer})
gasLimit uint64 = 31000
startGas uint64 = 10000
- value = big.NewInt(0)
+ value = uint256.NewInt(0)
contract = vm.NewContract(account{}, account{}, value, startGas)
)
@@ -76,7 +77,8 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
}
tracer.CaptureTxStart(gasLimit)
- tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
+ tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value.ToBig())
+
ret, err := env.Interpreter().Run(contract, []byte{}, false, nil)
tracer.CaptureEnd(ret, startGas-contract.Gas, err)
// Rest gas assumes no refund
@@ -193,7 +195,7 @@ func TestHaltBetweenSteps(t *testing.T) {
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
@@ -297,7 +299,7 @@ func TestEnterExit(t *testing.T) {
}
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
tracer.CaptureExit([]byte{}, 400, nil)
diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go
index a239530542..d6d6dec72f 100644
--- a/eth/tracers/logger/logger_test.go
+++ b/eth/tracers/logger/logger_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type dummyContractRef struct {
@@ -57,7 +58,7 @@ func TestStoreCapture(t *testing.T) {
var (
logger = NewStructLogger(nil)
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger})
- contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000)
+ contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go
index db7bb781d6..8470b5bb0c 100644
--- a/eth/tracers/native/call.go
+++ b/eth/tracers/native/call.go
@@ -168,7 +168,7 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
return
}
// Avoid processing nested calls when only caring about top call
- if t.config.OnlyTopCall && depth > 0 {
+ if t.config.OnlyTopCall && depth > 1 {
return
}
// Skip if tracing was interrupted
diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go
index 9351d044ab..f6adc54086 100644
--- a/eth/tracers/native/prestate.go
+++ b/eth/tracers/native/prestate.go
@@ -200,7 +200,7 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
modified := false
postAccount := &account{Storage: make(map[common.Hash]common.Hash)}
- newBalance := t.env.StateDB.GetBalance(addr)
+ newBalance := t.env.StateDB.GetBalance(addr).ToBig()
newNonce := t.env.StateDB.GetNonce(addr)
newCode := t.env.StateDB.GetCode(addr)
@@ -291,7 +291,7 @@ func (t *prestateTracer) lookupAccount(addr common.Address) {
}
t.pre[addr] = &account{
- Balance: t.env.StateDB.GetBalance(addr),
+ Balance: t.env.StateDB.GetBalance(addr).ToBig(),
Nonce: t.env.StateDB.GetNonce(addr),
Code: t.env.StateDB.GetCode(addr),
Storage: make(map[common.Hash]common.Hash),
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index ac4af25aa7..ed3a53f253 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -64,7 +64,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
GasLimit: gas,
BaseFee: big.NewInt(8),
}
- alloc := core.GenesisAlloc{}
+ alloc := types.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
// the address
loop := []byte{
@@ -72,18 +72,18 @@ func BenchmarkTransactionTrace(b *testing.B) {
byte(vm.PUSH1), 0, // jumpdestination
byte(vm.JUMP),
}
- alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
+ alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = types.Account{
Nonce: 1,
Code: loop,
Balance: big.NewInt(1),
}
- alloc[from] = core.GenesisAccount{
+ alloc[from] = types.Account{
Nonce: 1,
Code: []byte{},
Balance: big.NewInt(500000000000000),
}
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
+ defer state.Close()
// Create the tracer, the EVM environment and run it
tracer := logger.NewStructLogger(&logger.Config{
@@ -92,9 +92,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableMemory: false,
//EnableReturnData: false,
})
- evm := vm.NewEVM(blockContext, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
@@ -103,7 +102,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- snap := statedb.Snapshot()
+ snap := state.StateDB.Snapshot()
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
_, err = st.TransitionDb(context.Background())
@@ -111,7 +110,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
b.Fatal(err)
}
- statedb.RevertToSnapshot(snap)
+ state.StateDB.RevertToSnapshot(snap)
if have, want := len(tracer.StructLogs()), 244752; have != want {
b.Fatalf("trace wrong, want %d steps, have %d", want, have)
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 2745becbdb..24b5300253 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -339,10 +339,8 @@ func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*
var r *types.Receipt
err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
- if err == nil {
- if r == nil {
- return nil, ethereum.NotFound
- }
+ if err == nil && r == nil {
+ return nil, ethereum.NotFound
}
return r, err
@@ -721,6 +719,15 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasTipCap != nil {
arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
}
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
+ if msg.BlobGasFeeCap != nil {
+ arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
+ }
+ if msg.BlobHashes != nil {
+ arg["blobVersionedHashes"] = msg.BlobHashes
+ }
return arg
}
@@ -733,18 +740,20 @@ type rpcProgress struct {
PulledStates hexutil.Uint64
KnownStates hexutil.Uint64
- SyncedAccounts hexutil.Uint64
- SyncedAccountBytes hexutil.Uint64
- SyncedBytecodes hexutil.Uint64
- SyncedBytecodeBytes hexutil.Uint64
- SyncedStorage hexutil.Uint64
- SyncedStorageBytes hexutil.Uint64
- HealedTrienodes hexutil.Uint64
- HealedTrienodeBytes hexutil.Uint64
- HealedBytecodes hexutil.Uint64
- HealedBytecodeBytes hexutil.Uint64
- HealingTrienodes hexutil.Uint64
- HealingBytecode hexutil.Uint64
+ SyncedAccounts hexutil.Uint64
+ SyncedAccountBytes hexutil.Uint64
+ SyncedBytecodes hexutil.Uint64
+ SyncedBytecodeBytes hexutil.Uint64
+ SyncedStorage hexutil.Uint64
+ SyncedStorageBytes hexutil.Uint64
+ HealedTrienodes hexutil.Uint64
+ HealedTrienodeBytes hexutil.Uint64
+ HealedBytecodes hexutil.Uint64
+ HealedBytecodeBytes hexutil.Uint64
+ HealingTrienodes hexutil.Uint64
+ HealingBytecode hexutil.Uint64
+ TxIndexFinishedBlocks hexutil.Uint64
+ TxIndexRemainingBlocks hexutil.Uint64
}
func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
@@ -753,22 +762,24 @@ func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
}
return ðereum.SyncProgress{
- StartingBlock: uint64(p.StartingBlock),
- CurrentBlock: uint64(p.CurrentBlock),
- HighestBlock: uint64(p.HighestBlock),
- PulledStates: uint64(p.PulledStates),
- KnownStates: uint64(p.KnownStates),
- SyncedAccounts: uint64(p.SyncedAccounts),
- SyncedAccountBytes: uint64(p.SyncedAccountBytes),
- SyncedBytecodes: uint64(p.SyncedBytecodes),
- SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
- SyncedStorage: uint64(p.SyncedStorage),
- SyncedStorageBytes: uint64(p.SyncedStorageBytes),
- HealedTrienodes: uint64(p.HealedTrienodes),
- HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
- HealedBytecodes: uint64(p.HealedBytecodes),
- HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
- HealingTrienodes: uint64(p.HealingTrienodes),
- HealingBytecode: uint64(p.HealingBytecode),
+ StartingBlock: uint64(p.StartingBlock),
+ CurrentBlock: uint64(p.CurrentBlock),
+ HighestBlock: uint64(p.HighestBlock),
+ PulledStates: uint64(p.PulledStates),
+ KnownStates: uint64(p.KnownStates),
+ SyncedAccounts: uint64(p.SyncedAccounts),
+ SyncedAccountBytes: uint64(p.SyncedAccountBytes),
+ SyncedBytecodes: uint64(p.SyncedBytecodes),
+ SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
+ SyncedStorage: uint64(p.SyncedStorage),
+ SyncedStorageBytes: uint64(p.SyncedStorageBytes),
+ HealedTrienodes: uint64(p.HealedTrienodes),
+ HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
+ HealedBytecodes: uint64(p.HealedBytecodes),
+ HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
+ HealingTrienodes: uint64(p.HealingTrienodes),
+ HealingBytecode: uint64(p.HealingBytecode),
+ TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks),
+ TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks),
}
}
diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go
index b97fe4f62e..f4624b0682 100644
--- a/ethclient/gethclient/gethclient.go
+++ b/ethclient/gethclient/gethclient.go
@@ -247,7 +247,15 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
}
-
+ if msg.GasFeeCap != nil {
+ arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
+ }
+ if msg.GasTipCap != nil {
+ arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
+ }
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
return arg
}
diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go
index e062e45a93..294e43de3a 100644
--- a/ethclient/gethclient/gethclient_test.go
+++ b/ethclient/gethclient/gethclient_test.go
@@ -87,7 +87,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
func generateTestChain() (*core.Genesis, []*types.Block) {
genesis := &core.Genesis{
Config: params.AllEthashProtocolChanges,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
testEmpty: {Balance: big.NewInt(1)},
@@ -191,7 +191,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
From: testAddr,
To: &common.Address{},
Gas: 21000,
- GasPrice: big.NewInt(765625000),
+ GasPrice: big.NewInt(875000000),
Value: big.NewInt(1),
}
diff --git a/ethclient/simulated/backend.go b/ethclient/simulated/backend.go
new file mode 100644
index 0000000000..50c6d5f272
--- /dev/null
+++ b/ethclient/simulated/backend.go
@@ -0,0 +1,188 @@
+// Copyright 2023 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 simulated
+
+import (
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/catalyst"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/eth/filters"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// Client exposes the methods provided by the Ethereum RPC client.
+type Client interface {
+ ethereum.BlockNumberReader
+ ethereum.ChainReader
+ ethereum.ChainStateReader
+ ethereum.ContractCaller
+ ethereum.GasEstimator
+ ethereum.GasPricer
+ ethereum.GasPricer1559
+ ethereum.FeeHistoryReader
+ ethereum.LogFilterer
+ ethereum.PendingStateReader
+ ethereum.PendingContractCaller
+ ethereum.TransactionReader
+ ethereum.TransactionSender
+ ethereum.ChainIDReader
+}
+
+// simClient wraps ethclient. This exists to prevent extracting ethclient.Client
+// from the Client interface returned by Backend.
+type simClient struct {
+ *ethclient.Client
+}
+
+// Backend is a simulated blockchain. You can use it to test your contracts or
+// other code that interacts with the Ethereum chain.
+type Backend struct {
+ eth *eth.Ethereum
+ beacon *catalyst.SimulatedBeacon
+ client simClient
+}
+
+// NewBackend creates a new simulated blockchain that can be used as a backend for
+// contract bindings in unit tests.
+//
+// A simulated backend always uses chainID 1337.
+func NewBackend(alloc types.GenesisAlloc, options ...func(nodeConf *node.Config, ethConf *ethconfig.Config)) *Backend {
+ // Create the default configurations for the outer node shell and the Ethereum
+ // service to mutate with the options afterwards
+ nodeConf := node.DefaultConfig
+ nodeConf.DataDir = ""
+ nodeConf.P2P = p2p.Config{NoDiscovery: true}
+
+ ethConf := ethconfig.Defaults
+ ethConf.Genesis = &core.Genesis{
+ Config: params.AllDevChainProtocolChanges,
+ GasLimit: ethconfig.Defaults.Miner.GasCeil,
+ Alloc: alloc,
+ }
+ ethConf.SyncMode = downloader.FullSync
+ ethConf.TxPool.NoLocals = true
+
+ for _, option := range options {
+ option(&nodeConf, ðConf)
+ }
+ // Assemble the Ethereum stack to run the chain with
+ stack, err := node.New(&nodeConf)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ sim, err := newWithNode(stack, ðConf, 0)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ return sim
+}
+
+// newWithNode sets up a simulated backend on an existing node. The provided node
+// must not be started and will be started by this method.
+func newWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*Backend, error) {
+ backend, err := eth.New(stack, conf)
+ if err != nil {
+ return nil, err
+ }
+ // Register the filter system
+ filterSystem := filters.NewFilterSystem(backend.APIBackend, filters.Config{})
+ stack.RegisterAPIs([]rpc.API{{
+ Namespace: "eth",
+ Service: filters.NewFilterAPI(filterSystem, false, true),
+ }})
+ // Start the node
+ if err := stack.Start(); err != nil {
+ return nil, err
+ }
+ // Set up the simulated beacon
+ beacon, err := catalyst.NewSimulatedBeacon(blockPeriod, backend)
+ if err != nil {
+ return nil, err
+ }
+ // Reorg our chain back to genesis
+ if err := beacon.Fork(backend.BlockChain().GetCanonicalHash(0)); err != nil {
+ return nil, err
+ }
+ return &Backend{
+ eth: backend,
+ beacon: beacon,
+ client: simClient{ethclient.NewClient(stack.Attach())},
+ }, nil
+}
+
+// Close shuts down the simBackend.
+// The simulated backend can't be used afterwards.
+func (n *Backend) Close() error {
+ if n.client.Client != nil {
+ n.client.Close()
+ n.client = simClient{}
+ }
+ if n.beacon != nil {
+ err := n.beacon.Stop()
+ n.beacon = nil
+ return err
+ }
+ return nil
+}
+
+// Commit seals a block and moves the chain forward to a new empty block.
+func (n *Backend) Commit() common.Hash {
+ return n.beacon.Commit()
+}
+
+// Rollback removes all pending transactions, reverting to the last committed state.
+func (n *Backend) Rollback() {
+ n.beacon.Rollback()
+}
+
+// Fork creates a side-chain that can be used to simulate reorgs.
+//
+// This function should be called with the ancestor block where the new side
+// chain should be started. Transactions (old and new) can then be applied on
+// top and Commit-ed.
+//
+// Note, the side-chain will only become canonical (and trigger the events) when
+// it becomes longer. Until then CallContract will still operate on the current
+// canonical chain.
+//
+// There is a % chance that the side chain becomes canonical at the same length
+// to simulate live network behavior.
+func (n *Backend) Fork(parentHash common.Hash) error {
+ return n.beacon.Fork(parentHash)
+}
+
+// AdjustTime changes the block timestamp and creates a new block.
+// It can only be called on empty blocks.
+func (n *Backend) AdjustTime(adjustment time.Duration) error {
+ return n.beacon.AdjustTime(adjustment)
+}
+
+// Client returns a client that accesses the simulated chain.
+func (n *Backend) Client() Client {
+ return n.client
+}
diff --git a/ethclient/simulated/backend_test.go b/ethclient/simulated/backend_test.go
new file mode 100644
index 0000000000..a8fd7913c3
--- /dev/null
+++ b/ethclient/simulated/backend_test.go
@@ -0,0 +1,308 @@
+// 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 simulated
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "math/big"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var _ bind.ContractBackend = (Client)(nil)
+
+var (
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+)
+
+func simTestBackend(testAddr common.Address) *Backend {
+ return NewBackend(
+ types.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ },
+ )
+}
+
+func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
+ client := sim.Client()
+
+ // create a signed transaction to send
+ head, _ := client.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
+ addr := crypto.PubkeyToAddress(key.PublicKey)
+ chainid, _ := client.ChainID(context.Background())
+ nonce, err := client.PendingNonceAt(context.Background(), addr)
+ if err != nil {
+ return nil, err
+ }
+ tx := types.NewTx(&types.DynamicFeeTx{
+ ChainID: chainid,
+ Nonce: nonce,
+ GasTipCap: big.NewInt(params.GWei),
+ GasFeeCap: gasPrice,
+ Gas: 21000,
+ To: &addr,
+ })
+ return types.SignTx(tx, types.LatestSignerForChainID(chainid), key)
+}
+
+func TestNewBackend(t *testing.T) {
+ sim := NewBackend(types.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ num, err := client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 0 {
+ t.Fatalf("expected 0 got %v", num)
+ }
+ // Create a block
+ sim.Commit()
+ num, err = client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 1 {
+ t.Fatalf("expected 1 got %v", num)
+ }
+}
+
+func TestAdjustTime(t *testing.T) {
+ sim := NewBackend(types.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ block1, _ := client.BlockByNumber(context.Background(), nil)
+
+ // Create a block
+ if err := sim.AdjustTime(time.Minute); err != nil {
+ t.Fatal(err)
+ }
+ block2, _ := client.BlockByNumber(context.Background(), nil)
+ prevTime := block1.Time()
+ newTime := block2.Time()
+ if newTime-prevTime != uint64(time.Minute) {
+ t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime)
+ }
+}
+
+func TestSendTransaction(t *testing.T) {
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ signedTx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Errorf("could not create transaction: %v", err)
+ }
+ // send tx to simulated backend
+ err = client.SendTransaction(ctx, signedTx)
+ if err != nil {
+ t.Errorf("could not add tx to pending block: %v", err)
+ }
+ sim.Commit()
+ block, err := client.BlockByNumber(ctx, big.NewInt(1))
+ if err != nil {
+ t.Errorf("could not get block at height 1: %v", err)
+ }
+
+ if signedTx.Hash() != block.Transactions()[0].Hash() {
+ t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
+ }
+}
+
+// TestFork check that the chain length after a reorg is correct.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Mine n blocks with n ∈ [0, 20].
+// 3. Assert that the chain length is n.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine n+1 blocks which should trigger a reorg.
+// 6. Assert that the chain length is n+1.
+// Since Commit() was called 2n+1 times in total,
+// having a chain length of just n+1 means that a reorg occurred.
+func TestFork(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ n := int(rand.Int31n(21))
+ for i := 0; i < n; i++ {
+ sim.Commit()
+ }
+
+ // 3.
+ b, _ := client.BlockNumber(ctx)
+ if b != uint64(n) {
+ t.Error("wrong chain length")
+ }
+
+ // 4.
+ sim.Fork(parent.Hash())
+
+ // 5.
+ for i := 0; i < n+1; i++ {
+ sim.Commit()
+ }
+
+ // 6.
+ b, _ = client.BlockNumber(ctx)
+ if b != uint64(n+1) {
+ t.Error("wrong chain length")
+ }
+}
+
+// TestForkResendTx checks that re-sending a TX after a fork
+// is possible and does not cause a "nonce mismatch" panic.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Send a transaction.
+// 3. Check that the TX is included in block 1.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine a block, Re-send the transaction and mine another one.
+// 6. Check that the TX is now included in block 2.
+func TestForkResendTx(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ tx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Fatalf("could not create transaction: %v", err)
+ }
+ client.SendTransaction(ctx, tx)
+ sim.Commit()
+
+ // 3.
+ receipt, _ := client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 1 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+
+ // 4.
+ if err := sim.Fork(parent.Hash()); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // 5.
+ sim.Commit()
+ if err := client.SendTransaction(ctx, tx); err != nil {
+ t.Fatalf("sending transaction: %v", err)
+ }
+ sim.Commit()
+ receipt, _ = client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 2 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+}
+
+func TestCommitReturnValue(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // Test if Commit returns the correct block hash
+ h1 := sim.Commit()
+ cur, _ := client.HeaderByNumber(ctx, nil)
+ if h1 != cur.Hash() {
+ t.Error("Commit did not return the hash of the last block.")
+ }
+
+ // Create a block in the original chain (containing a transaction to force different block hashes)
+ head, _ := client.HeaderByNumber(ctx, nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
+ _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
+ tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
+ client.SendTransaction(ctx, tx)
+
+ h2 := sim.Commit()
+
+ // Create another block in the original chain
+ sim.Commit()
+
+ // Fork at the first bock
+ if err := sim.Fork(h1); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // Test if Commit returns the correct block hash after the reorg
+ h2fork := sim.Commit()
+ if h2 == h2fork {
+ t.Error("The block in the fork and the original block are the same block!")
+ }
+ if header, err := client.HeaderByHash(ctx, h2fork); err != nil || header == nil {
+ t.Error("Could not retrieve the just created block (side-chain)")
+ }
+}
+
+// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
+// block's parent rather than the canonical head's parent.
+func TestAdjustTimeAfterFork(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ sim.Commit() // h1
+ h1, _ := client.HeaderByNumber(ctx, nil)
+
+ sim.Commit() // h2
+ sim.Fork(h1.Hash())
+ sim.AdjustTime(1 * time.Second)
+ sim.Commit()
+
+ head, _ := client.HeaderByNumber(ctx, nil)
+ if head.Number.Uint64() == 2 && head.ParentHash != h1.Hash() {
+ t.Errorf("failed to build block on fork")
+ }
+}
diff --git a/ethclient/simulated/options.go b/ethclient/simulated/options.go
new file mode 100644
index 0000000000..6db995c917
--- /dev/null
+++ b/ethclient/simulated/options.go
@@ -0,0 +1,55 @@
+// Copyright 2024 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 simulated
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/node"
+)
+
+// WithBlockGasLimit configures the simulated backend to target a specific gas limit
+// when producing blocks.
+func WithBlockGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.Genesis.GasLimit = gaslimit
+ ethConf.Miner.GasCeil = gaslimit
+ }
+}
+
+// WithCallGasLimit configures the simulated backend to cap eth_calls to a specific
+// gas limit when running client operations.
+func WithCallGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.RPCGasCap = gaslimit
+ }
+}
+
+// WithMinerMinTip configures the simulated backend to require a specific minimum
+// gas tip for a transaction to be included.
+//
+// 0 is not possible as a live Geth node would reject that due to DoS protection,
+// so the simulated backend will replicate that behavior for consistency.
+func WithMinerMinTip(tip *big.Int) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ if tip == nil || tip.Cmp(new(big.Int)) <= 0 {
+ panic("invalid miner minimum tip")
+ }
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.Miner.GasPrice = tip
+ }
+}
diff --git a/ethclient/simulated/options_test.go b/ethclient/simulated/options_test.go
new file mode 100644
index 0000000000..9ff2be5ff9
--- /dev/null
+++ b/ethclient/simulated/options_test.go
@@ -0,0 +1,74 @@
+// Copyright 2024 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 simulated
+
+import (
+ "context"
+ "math/big"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// Tests that the simulator starts with the initial gas limit in the genesis block,
+// and that it keeps the same target value.
+func TestWithBlockGasLimitOption(t *testing.T) {
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(types.GenesisAlloc{}, WithBlockGasLimit(12_345_678))
+ defer sim.Close()
+
+ client := sim.Client()
+ genesis, err := client.BlockByNumber(context.Background(), big.NewInt(0))
+ if err != nil {
+ t.Fatalf("failed to retrieve genesis block: %v", err)
+ }
+ if genesis.GasLimit() != 12_345_678 {
+ t.Errorf("genesis gas limit mismatch: have %v, want %v", genesis.GasLimit(), 12_345_678)
+ }
+ // Produce a number of blocks and verify the locked in gas target
+ sim.Commit()
+ head, err := client.BlockByNumber(context.Background(), big.NewInt(1))
+ if err != nil {
+ t.Fatalf("failed to retrieve head block: %v", err)
+ }
+ if head.GasLimit() != 12_345_678 {
+ t.Errorf("head gas limit mismatch: have %v, want %v", head.GasLimit(), 12_345_678)
+ }
+}
+
+// Tests that the simulator honors the RPC call caps set by the options.
+func TestWithCallGasLimitOption(t *testing.T) {
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(types.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ }, WithCallGasLimit(params.TxGas-1))
+ defer sim.Close()
+
+ client := sim.Client()
+ _, err := client.CallContract(context.Background(), ethereum.CallMsg{
+ From: testAddr,
+ To: &testAddr,
+ Gas: 21000,
+ }, nil)
+ if !strings.Contains(err.Error(), core.ErrIntrinsicGas.Error()) {
+ t.Fatalf("error mismatch: have %v, want %v", err, core.ErrIntrinsicGas)
+ }
+}
diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go
index f281725965..04797525ec 100644
--- a/ethstats/ethstats.go
+++ b/ethstats/ethstats.go
@@ -734,12 +734,6 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
}
}
- // It's weird, but it's possible that the block is nil here.
- // even though the check for error is done above.
- if block == nil {
- return nil
- }
-
header = block.Header()
td = fullBackend.GetTd(context.Background(), header.Hash())
diff --git a/go.mod b/go.mod
index 17128decbd..feb1e7835e 100644
--- a/go.mod
+++ b/go.mod
@@ -29,8 +29,9 @@ require (
github.com/emirpasic/gods v1.18.1
github.com/ethereum/c-kzg-4844 v0.4.3
github.com/fatih/color v1.16.0
+ github.com/ferranbt/fastssz v0.1.2
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
- github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
+ github.com/fjl/memsize v0.0.2
github.com/fsnotify/fsnotify v1.6.0
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46
@@ -48,7 +49,7 @@ require (
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/hashicorp/hcl/v2 v2.10.1
github.com/heimdalr/dag v1.2.1
- github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7
+ github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.4
github.com/huin/goupnp v1.3.0
@@ -150,10 +151,12 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kilic/bls12-381 v0.1.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.1 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
diff --git a/go.sum b/go.sum
index de4c422601..45b4fd5d26 100644
--- a/go.sum
+++ b/go.sum
@@ -1140,10 +1140,13 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk=
+github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
-github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
+github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
+github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -1500,8 +1503,9 @@ github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpT
github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/heimdalr/dag v1.2.1 h1:XJOMaoWqJK1UKdp+4zaO2uwav9GFbHMGCirdViKMRIQ=
github.com/heimdalr/dag v1.2.1/go.mod h1:Of/wUB7Yoj4dwiOcGOOYIq6MHlPF/8/QMBKFJpwg+yc=
-github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw=
github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
+github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=
+github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
@@ -1636,7 +1640,10 @@ github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
+github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -1748,6 +1755,8 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
+github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
+github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
@@ -1961,6 +1970,8 @@ github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSg
github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY=
github.com/protolambda/bls12-381-util v0.1.0 h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk=
github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4=
+github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h1:cSo6/vk8YpvkLbk9v3FO97cakNmUoxwi2KMP8hd5WIw=
+github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
diff --git a/graphql/graphql.go b/graphql/graphql.go
index 60ca71850e..94225d97f3 100644
--- a/graphql/graphql.go
+++ b/graphql/graphql.go
@@ -100,7 +100,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
if err != nil {
return hexutil.Big{}, err
}
- balance := state.GetBalance(a.address)
+ balance := state.GetBalance(a.address).ToBig()
if balance == nil {
return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address)
}
@@ -230,8 +230,8 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block)
return t.tx, t.block
}
// Try to return an already finalized transaction
- tx, blockHash, _, index, err := t.r.backend.GetTransaction(ctx, t.hash)
- if err == nil && tx != nil {
+ found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash)
+ if found {
t.tx = tx
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
t.block = &Block{
@@ -1509,6 +1509,12 @@ func (s *SyncState) HealingTrienodes() hexutil.Uint64 {
func (s *SyncState) HealingBytecode() hexutil.Uint64 {
return hexutil.Uint64(s.progress.HealingBytecode)
}
+func (s *SyncState) TxIndexFinishedBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexFinishedBlocks)
+}
+func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexRemainingBlocks)
+}
// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
// yet received the latest block headers from its pears. In case it is synchronizing:
@@ -1527,11 +1533,13 @@ func (s *SyncState) HealingBytecode() hexutil.Uint64 {
// - healedBytecodeBytes: number of bytecodes persisted to disk
// - healingTrienodes: number of state trie nodes pending
// - healingBytecode: number of bytecodes pending
+// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
+// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
func (r *Resolver) Syncing() (*SyncState, error) {
progress := r.backend.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return nil, nil
}
// Otherwise gather the block sync stats
diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go
index 73ef17c9c2..3a9c66b5b1 100644
--- a/graphql/graphql_test.go
+++ b/graphql/graphql_test.go
@@ -189,7 +189,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: big.NewInt(1048576),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xdad sloads 0x00 and 0x01
dad: {
@@ -287,7 +287,7 @@ func TestGraphQLConcurrentResolvers(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: big.NewInt(1048576),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
dad: {
// LOG0(0, 0), LOG0(0, 0), RETURN(0, 0)
@@ -387,7 +387,7 @@ func TestWithdrawals(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: common.Big1,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
},
}
diff --git a/interfaces.go b/interfaces.go
index 2ebe1cf562..0ece6fad7a 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -120,6 +120,18 @@ type SyncProgress struct {
HealingTrienodes uint64 // Number of state trie nodes pending
HealingBytecode uint64 // Number of bytecodes pending
+
+ // "transaction indexing" fields
+ TxIndexFinishedBlocks uint64 // Number of blocks whose transactions are already indexed
+ TxIndexRemainingBlocks uint64 // Number of blocks whose transactions are not indexed yet
+}
+
+// Done returns the indicator if the initial sync is finished or not.
+func (prog SyncProgress) Done() bool {
+ if prog.CurrentBlock < prog.HighestBlock {
+ return false
+ }
+ return prog.TxIndexRemainingBlocks == 0
}
// ChainSyncReader wraps access to the node's current sync status. If there's no
@@ -140,6 +152,10 @@ type CallMsg struct {
Data []byte // input data, usually an ABI-encoded contract method invocation
AccessList types.AccessList // EIP-2930 access list.
+
+ // For BlobTxType
+ BlobGasFeeCap *big.Int
+ BlobHashes []common.Hash
}
// A ContractCaller provides contract calls, essentially transactions that are executed by
@@ -199,6 +215,16 @@ type GasPricer interface {
SuggestGasPrice(ctx context.Context) (*big.Int, error)
}
+// GasPricer1559 provides access to the EIP-1559 gas price oracle.
+type GasPricer1559 interface {
+ SuggestGasTipCap(ctx context.Context) (*big.Int, error)
+}
+
+// FeeHistoryReader provides access to the fee history oracle.
+type FeeHistoryReader interface {
+ FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*FeeHistory, error)
+}
+
// FeeHistory provides recent fee market data that consumers can use to determine
// a reasonable maxPriorityFeePerGas value.
type FeeHistory struct {
@@ -264,3 +290,13 @@ type ChainValidator interface {
RemoveMilestoneID(milestoneId string)
GetMilestoneIDsList() []string
}
+
+// BlockNumberReader provides access to the current block number.
+type BlockNumberReader interface {
+ BlockNumber(ctx context.Context) (uint64, error)
+}
+
+// ChainIDReader provides access to the chain ID.
+type ChainIDReader interface {
+ ChainID(ctx context.Context) (*big.Int, error)
+}
diff --git a/internal/build/download.go b/internal/build/download.go
index d4605a9019..24016b0092 100644
--- a/internal/build/download.go
+++ b/internal/build/download.go
@@ -40,8 +40,7 @@ func MustLoadChecksums(file string) *ChecksumDB {
if err != nil {
log.Fatal("can't load checksum file: " + err.Error())
}
-
- return &ChecksumDB{strings.Split(string(content), "\n")}
+ return &ChecksumDB{strings.Split(strings.ReplaceAll(string(content), "\r\n", "\n"), "\n")}
}
// Verify checks whether the given file is valid according to the checksum database.
diff --git a/internal/build/gotool.go b/internal/build/gotool.go
index 5f76d829ec..5d4b467da5 100644
--- a/internal/build/gotool.go
+++ b/internal/build/gotool.go
@@ -155,7 +155,6 @@ func Version(csdb *ChecksumDB, version string) (string, error) {
continue
}
if parts[0] == version {
- log.Printf("Found version %q", parts[1])
return parts[1], nil
}
}
diff --git a/internal/build/util.go b/internal/build/util.go
index 937e648b6e..99ca164d70 100644
--- a/internal/build/util.go
+++ b/internal/build/util.go
@@ -74,6 +74,27 @@ func MustRunCommand(cmd string, args ...string) {
MustRun(exec.Command(cmd, args...))
}
+// MustRunCommandWithOutput runs the given command, and ensures that some output will be
+// printed while it runs. This is useful for CI builds where the process will be stopped
+// when there is no output.
+func MustRunCommandWithOutput(cmd string, args ...string) {
+ interval := time.NewTicker(time.Minute)
+ done := make(chan struct{})
+ defer interval.Stop()
+ defer close(done)
+ go func() {
+ for {
+ select {
+ case <-interval.C:
+ fmt.Printf("Waiting for command %q\n", cmd)
+ case <-done:
+ return
+ }
+ }
+ }()
+ MustRun(exec.Command(cmd, args...))
+}
+
var warnedAboutGit bool
// RunGit runs a git subcommand and returns its output.
diff --git a/internal/cli/snapshot.go b/internal/cli/snapshot.go
index a575210bb5..ce4798d8a2 100644
--- a/internal/cli/snapshot.go
+++ b/internal/cli/snapshot.go
@@ -17,7 +17,7 @@ import (
"github.com/ethereum/go-ethereum/internal/cli/server"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/prometheus/tsdb/fileutil"
@@ -373,7 +373,7 @@ func (c *PruneBlockCommand) validateAgainstSnapshot(stack *node.Node, dbHandles
}
// Make sure the MPT and snapshot matches before pruning, otherwise the node can not start.
- snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb, trie.HashDefaults), headBlock.Root())
+ snaptree, err := snapshot.New(snapconfig, chaindb, triedb.NewDatabase(chaindb, triedb.HashDefaults), headBlock.Root())
if err != nil {
log.Error("Unable to load snapshot", "err", err)
return err // The relevant snapshot(s) might not exist
diff --git a/internal/cli/snapshot_test.go b/internal/cli/snapshot_test.go
index d17893ddda..1a70d9c5af 100644
--- a/internal/cli/snapshot_test.go
+++ b/internal/cli/snapshot_test.go
@@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/stretchr/testify/require"
)
@@ -158,7 +158,7 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
defer db.Close()
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
// Initialize a fresh chain with only a genesis block
blockchain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
require.NoError(t, err, "failed to create chain")
diff --git a/internal/debug/flags.go b/internal/debug/flags.go
index 23e4745e8c..dac878a7b1 100644
--- a/internal/debug/flags.go
+++ b/internal/debug/flags.go
@@ -168,22 +168,12 @@ var Flags = []cli.Flag{
}
var (
- glogger *log.GlogHandler
- logOutputFile io.WriteCloser
- defaultTerminalHandler *log.TerminalHandler
+ glogger *log.GlogHandler
+ logOutputFile io.WriteCloser
)
func init() {
- defaultTerminalHandler = log.NewTerminalHandler(os.Stderr, false)
- glogger = log.NewGlogHandler(defaultTerminalHandler)
- glogger.Verbosity(log.LvlInfo)
- log.SetDefault(log.NewLogger(glogger))
-}
-
-func ResetLogging() {
- if defaultTerminalHandler != nil {
- defaultTerminalHandler.ResetFieldPadding()
- }
+ glogger = log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
}
// Setup initializes profiling and logging based on the CLI flags.
diff --git a/internal/era/accumulator.go b/internal/era/accumulator.go
new file mode 100644
index 0000000000..19e03973f1
--- /dev/null
+++ b/internal/era/accumulator.go
@@ -0,0 +1,90 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ ssz "github.com/ferranbt/fastssz"
+)
+
+// ComputeAccumulator calculates the SSZ hash tree root of the Era1
+// accumulator of header records.
+func ComputeAccumulator(hashes []common.Hash, tds []*big.Int) (common.Hash, error) {
+ if len(hashes) != len(tds) {
+ return common.Hash{}, fmt.Errorf("must have equal number hashes as td values")
+ }
+ if len(hashes) > MaxEra1Size {
+ return common.Hash{}, fmt.Errorf("too many records: have %d, max %d", len(hashes), MaxEra1Size)
+ }
+ hh := ssz.NewHasher()
+ for i := range hashes {
+ rec := headerRecord{hashes[i], tds[i]}
+ root, err := rec.HashTreeRoot()
+ if err != nil {
+ return common.Hash{}, err
+ }
+ hh.Append(root[:])
+ }
+ hh.MerkleizeWithMixin(0, uint64(len(hashes)), uint64(MaxEra1Size))
+ return hh.HashRoot()
+}
+
+// headerRecord is an individual record for a historical header.
+//
+// See https://github.com/ethereum/portal-network-specs/blob/master/history-network.md#the-header-accumulator
+// for more information.
+type headerRecord struct {
+ Hash common.Hash
+ TotalDifficulty *big.Int
+}
+
+// GetTree completes the ssz.HashRoot interface, but is unused.
+func (h *headerRecord) GetTree() (*ssz.Node, error) {
+ return nil, nil
+}
+
+// HashTreeRoot ssz hashes the headerRecord object.
+func (h *headerRecord) HashTreeRoot() ([32]byte, error) {
+ return ssz.HashWithDefaultHasher(h)
+}
+
+// HashTreeRootWith ssz hashes the headerRecord object with a hasher.
+func (h *headerRecord) HashTreeRootWith(hh ssz.HashWalker) (err error) {
+ hh.PutBytes(h.Hash[:])
+ td := bigToBytes32(h.TotalDifficulty)
+ hh.PutBytes(td[:])
+ hh.Merkleize(0)
+ return
+}
+
+// bigToBytes32 converts a big.Int into a little-endian 32-byte array.
+func bigToBytes32(n *big.Int) (b [32]byte) {
+ n.FillBytes(b[:])
+ reverseOrder(b[:])
+ return
+}
+
+// reverseOrder reverses the byte order of a slice.
+func reverseOrder(b []byte) []byte {
+ for i := 0; i < 16; i++ {
+ b[i], b[32-i-1] = b[32-i-1], b[i]
+ }
+ return b
+}
diff --git a/internal/era/builder.go b/internal/era/builder.go
new file mode 100644
index 0000000000..9217c049f3
--- /dev/null
+++ b/internal/era/builder.go
@@ -0,0 +1,224 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+package era
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/era/e2store"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/golang/snappy"
+)
+
+// Builder is used to create Era1 archives of block data.
+//
+// Era1 files are themselves e2store files. For more information on this format,
+// see https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md.
+//
+// The overall structure of an Era1 file follows closely the structure of an Era file
+// which contains consensus Layer data (and as a byproduct, EL data after the merge).
+//
+// The structure can be summarized through this definition:
+//
+// era1 := Version | block-tuple* | other-entries* | Accumulator | BlockIndex
+// block-tuple := CompressedHeader | CompressedBody | CompressedReceipts | TotalDifficulty
+//
+// Each basic element is its own entry:
+//
+// Version = { type: [0x65, 0x32], data: nil }
+// CompressedHeader = { type: [0x03, 0x00], data: snappyFramed(rlp(header)) }
+// CompressedBody = { type: [0x04, 0x00], data: snappyFramed(rlp(body)) }
+// CompressedReceipts = { type: [0x05, 0x00], data: snappyFramed(rlp(receipts)) }
+// TotalDifficulty = { type: [0x06, 0x00], data: uint256(header.total_difficulty) }
+// AccumulatorRoot = { type: [0x07, 0x00], data: accumulator-root }
+// BlockIndex = { type: [0x32, 0x66], data: block-index }
+//
+// Accumulator is computed by constructing an SSZ list of header-records of length at most
+// 8192 and then calculating the hash_tree_root of that list.
+//
+// header-record := { block-hash: Bytes32, total-difficulty: Uint256 }
+// accumulator := hash_tree_root([]header-record, 8192)
+//
+// BlockIndex stores relative offsets to each compressed block entry. The
+// format is:
+//
+// block-index := starting-number | index | index | index ... | count
+//
+// starting-number is the first block number in the archive. Every index is a
+// defined relative to beginning of the record. The total number of block
+// entries in the file is recorded with count.
+//
+// Due to the accumulator size limit of 8192, the maximum number of blocks in
+// an Era1 batch is also 8192.
+type Builder struct {
+ w *e2store.Writer
+ startNum *uint64
+ startTd *big.Int
+ indexes []uint64
+ hashes []common.Hash
+ tds []*big.Int
+ written int
+
+ buf *bytes.Buffer
+ snappy *snappy.Writer
+}
+
+// NewBuilder returns a new Builder instance.
+func NewBuilder(w io.Writer) *Builder {
+ buf := bytes.NewBuffer(nil)
+ return &Builder{
+ w: e2store.NewWriter(w),
+ buf: buf,
+ snappy: snappy.NewBufferedWriter(buf),
+ }
+}
+
+// Add writes a compressed block entry and compressed receipts entry to the
+// underlying e2store file.
+func (b *Builder) Add(block *types.Block, receipts types.Receipts, td *big.Int) error {
+ eh, err := rlp.EncodeToBytes(block.Header())
+ if err != nil {
+ return err
+ }
+ eb, err := rlp.EncodeToBytes(block.Body())
+ if err != nil {
+ return err
+ }
+ er, err := rlp.EncodeToBytes(receipts)
+ if err != nil {
+ return err
+ }
+ return b.AddRLP(eh, eb, er, block.NumberU64(), block.Hash(), td, block.Difficulty())
+}
+
+// AddRLP writes a compressed block entry and compressed receipts entry to the
+// underlying e2store file.
+func (b *Builder) AddRLP(header, body, receipts []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error {
+ // Write Era1 version entry before first block.
+ if b.startNum == nil {
+ n, err := b.w.Write(TypeVersion, nil)
+ if err != nil {
+ return err
+ }
+ startNum := number
+ b.startNum = &startNum
+ b.startTd = new(big.Int).Sub(td, difficulty)
+ b.written += n
+ }
+ if len(b.indexes) >= MaxEra1Size {
+ return fmt.Errorf("exceeds maximum batch size of %d", MaxEra1Size)
+ }
+
+ b.indexes = append(b.indexes, uint64(b.written))
+ b.hashes = append(b.hashes, hash)
+ b.tds = append(b.tds, td)
+
+ // Write block data.
+ if err := b.snappyWrite(TypeCompressedHeader, header); err != nil {
+ return err
+ }
+ if err := b.snappyWrite(TypeCompressedBody, body); err != nil {
+ return err
+ }
+ if err := b.snappyWrite(TypeCompressedReceipts, receipts); err != nil {
+ return err
+ }
+
+ // Also write total difficulty, but don't snappy encode.
+ btd := bigToBytes32(td)
+ n, err := b.w.Write(TypeTotalDifficulty, btd[:])
+ b.written += n
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Finalize computes the accumulator and block index values, then writes the
+// corresponding e2store entries.
+func (b *Builder) Finalize() (common.Hash, error) {
+ if b.startNum == nil {
+ return common.Hash{}, fmt.Errorf("finalize called on empty builder")
+ }
+ // Compute accumulator root and write entry.
+ root, err := ComputeAccumulator(b.hashes, b.tds)
+ if err != nil {
+ return common.Hash{}, fmt.Errorf("error calculating accumulator root: %w", err)
+ }
+ n, err := b.w.Write(TypeAccumulator, root[:])
+ b.written += n
+ if err != nil {
+ return common.Hash{}, fmt.Errorf("error writing accumulator: %w", err)
+ }
+ // Get beginning of index entry to calculate block relative offset.
+ base := int64(b.written)
+
+ // Construct block index. Detailed format described in Builder
+ // documentation, but it is essentially encoded as:
+ // "start | index | index | ... | count"
+ var (
+ count = len(b.indexes)
+ index = make([]byte, 16+count*8)
+ )
+ binary.LittleEndian.PutUint64(index, *b.startNum)
+ // Each offset is relative from the position it is encoded in the
+ // index. This means that even if the same block was to be included in
+ // the index twice (this would be invalid anyways), the relative offset
+ // would be different. The idea with this is that after reading a
+ // relative offset, the corresponding block can be quickly read by
+ // performing a seek relative to the current position.
+ for i, offset := range b.indexes {
+ relative := int64(offset) - base
+ binary.LittleEndian.PutUint64(index[8+i*8:], uint64(relative))
+ }
+ binary.LittleEndian.PutUint64(index[8+count*8:], uint64(count))
+
+ // Finally, write the block index entry.
+ if _, err := b.w.Write(TypeBlockIndex, index); err != nil {
+ return common.Hash{}, fmt.Errorf("unable to write block index: %w", err)
+ }
+
+ return root, nil
+}
+
+// snappyWrite is a small helper to take care snappy encoding and writing an e2store entry.
+func (b *Builder) snappyWrite(typ uint16, in []byte) error {
+ var (
+ buf = b.buf
+ s = b.snappy
+ )
+ buf.Reset()
+ s.Reset(buf)
+ if _, err := b.snappy.Write(in); err != nil {
+ return fmt.Errorf("error snappy encoding: %w", err)
+ }
+ if err := s.Flush(); err != nil {
+ return fmt.Errorf("error flushing snappy encoding: %w", err)
+ }
+ n, err := b.w.Write(typ, b.buf.Bytes())
+ b.written += n
+ if err != nil {
+ return fmt.Errorf("error writing e2store entry: %w", err)
+ }
+ return nil
+}
diff --git a/internal/era/e2store/e2store.go b/internal/era/e2store/e2store.go
new file mode 100644
index 0000000000..d85b3e44e9
--- /dev/null
+++ b/internal/era/e2store/e2store.go
@@ -0,0 +1,220 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package e2store
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+)
+
+const (
+ headerSize = 8
+ valueSizeLimit = 1024 * 1024 * 50
+)
+
+// Entry is a variable-length-data record in an e2store.
+type Entry struct {
+ Type uint16
+ Value []byte
+}
+
+// Writer writes entries using e2store encoding.
+// For more information on this format, see:
+// https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md
+type Writer struct {
+ w io.Writer
+}
+
+// NewWriter returns a new Writer that writes to w.
+func NewWriter(w io.Writer) *Writer {
+ return &Writer{w}
+}
+
+// Write writes a single e2store entry to w.
+// An entry is encoded in a type-length-value format. The first 8 bytes of the
+// record store the type (2 bytes), the length (4 bytes), and some reserved
+// data (2 bytes). The remaining bytes store b.
+func (w *Writer) Write(typ uint16, b []byte) (int, error) {
+ buf := make([]byte, headerSize)
+ binary.LittleEndian.PutUint16(buf, typ)
+ binary.LittleEndian.PutUint32(buf[2:], uint32(len(b)))
+
+ // Write header.
+ if n, err := w.w.Write(buf); err != nil {
+ return n, err
+ }
+ // Write value, return combined write size.
+ n, err := w.w.Write(b)
+ return n + headerSize, err
+}
+
+// A Reader reads entries from an e2store-encoded file.
+// For more information on this format, see
+// https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md
+type Reader struct {
+ r io.ReaderAt
+ offset int64
+}
+
+// NewReader returns a new Reader that reads from r.
+func NewReader(r io.ReaderAt) *Reader {
+ return &Reader{r, 0}
+}
+
+// Read reads one Entry from r.
+func (r *Reader) Read() (*Entry, error) {
+ var e Entry
+ n, err := r.ReadAt(&e, r.offset)
+ if err != nil {
+ return nil, err
+ }
+ r.offset += int64(n)
+ return &e, nil
+}
+
+// ReadAt reads one Entry from r at the specified offset.
+func (r *Reader) ReadAt(entry *Entry, off int64) (int, error) {
+ typ, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return 0, err
+ }
+ entry.Type = typ
+
+ // Check length bounds.
+ if length > valueSizeLimit {
+ return headerSize, fmt.Errorf("item larger than item size limit %d: have %d", valueSizeLimit, length)
+ }
+ if length == 0 {
+ return headerSize, nil
+ }
+
+ // Read value.
+ val := make([]byte, length)
+ if n, err := r.r.ReadAt(val, off+headerSize); err != nil {
+ n += headerSize
+ // An entry with a non-zero length should not return EOF when
+ // reading the value.
+ if err == io.EOF {
+ return n, io.ErrUnexpectedEOF
+ }
+ return n, err
+ }
+ entry.Value = val
+ return int(headerSize + length), nil
+}
+
+// ReaderAt returns an io.Reader delivering value data for the entry at
+// the specified offset. If the entry type does not match the expected type, an
+// error is returned.
+func (r *Reader) ReaderAt(expectedType uint16, off int64) (io.Reader, int, error) {
+ // problem = need to return length+headerSize not just value length via section reader
+ typ, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return nil, headerSize, err
+ }
+ if typ != expectedType {
+ return nil, headerSize, fmt.Errorf("wrong type, want %d have %d", expectedType, typ)
+ }
+ if length > valueSizeLimit {
+ return nil, headerSize, fmt.Errorf("item larger than item size limit %d: have %d", valueSizeLimit, length)
+ }
+ return io.NewSectionReader(r.r, off+headerSize, int64(length)), headerSize + int(length), nil
+}
+
+// LengthAt reads the header at off and returns the total length of the entry,
+// including header.
+func (r *Reader) LengthAt(off int64) (int64, error) {
+ _, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return 0, err
+ }
+ return int64(length) + headerSize, nil
+}
+
+// ReadMetadataAt reads the header metadata at the given offset.
+func (r *Reader) ReadMetadataAt(off int64) (typ uint16, length uint32, err error) {
+ b := make([]byte, headerSize)
+ if n, err := r.r.ReadAt(b, off); err != nil {
+ if err == io.EOF && n > 0 {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ return 0, 0, err
+ }
+ typ = binary.LittleEndian.Uint16(b)
+ length = binary.LittleEndian.Uint32(b[2:])
+
+ // Check reserved bytes of header.
+ if b[6] != 0 || b[7] != 0 {
+ return 0, 0, fmt.Errorf("reserved bytes are non-zero")
+ }
+
+ return typ, length, nil
+}
+
+// Find returns the first entry with the matching type.
+func (r *Reader) Find(want uint16) (*Entry, error) {
+ var (
+ off int64
+ typ uint16
+ length uint32
+ err error
+ )
+ for {
+ typ, length, err = r.ReadMetadataAt(off)
+ if err == io.EOF {
+ return nil, io.EOF
+ } else if err != nil {
+ return nil, err
+ }
+ if typ == want {
+ var e Entry
+ if _, err := r.ReadAt(&e, off); err != nil {
+ return nil, err
+ }
+ return &e, nil
+ }
+ off += int64(headerSize + length)
+ }
+}
+
+// FindAll returns all entries with the matching type.
+func (r *Reader) FindAll(want uint16) ([]*Entry, error) {
+ var (
+ off int64
+ typ uint16
+ length uint32
+ entries []*Entry
+ err error
+ )
+ for {
+ typ, length, err = r.ReadMetadataAt(off)
+ if err == io.EOF {
+ return entries, nil
+ } else if err != nil {
+ return entries, err
+ }
+ if typ == want {
+ e := new(Entry)
+ if _, err := r.ReadAt(e, off); err != nil {
+ return entries, err
+ }
+ entries = append(entries, e)
+ }
+ off += int64(headerSize + length)
+ }
+}
diff --git a/internal/era/e2store/e2store_test.go b/internal/era/e2store/e2store_test.go
new file mode 100644
index 0000000000..febcffe4cf
--- /dev/null
+++ b/internal/era/e2store/e2store_test.go
@@ -0,0 +1,150 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package e2store
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestEncode(t *testing.T) {
+ for _, test := range []struct {
+ entries []Entry
+ want string
+ name string
+ }{
+ {
+ name: "emptyEntry",
+ entries: []Entry{{0xffff, nil}},
+ want: "ffff000000000000",
+ },
+ {
+ name: "beef",
+ entries: []Entry{{42, common.Hex2Bytes("beef")}},
+ want: "2a00020000000000beef",
+ },
+ {
+ name: "twoEntries",
+ entries: []Entry{
+ {42, common.Hex2Bytes("beef")},
+ {9, common.Hex2Bytes("abcdabcd")},
+ },
+ want: "2a00020000000000beef0900040000000000abcdabcd",
+ },
+ } {
+ tt := test
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+ var (
+ b = bytes.NewBuffer(nil)
+ w = NewWriter(b)
+ )
+ for _, e := range tt.entries {
+ if _, err := w.Write(e.Type, e.Value); err != nil {
+ t.Fatalf("encoding error: %v", err)
+ }
+ }
+ if want, have := common.FromHex(tt.want), b.Bytes(); !bytes.Equal(want, have) {
+ t.Fatalf("encoding mismatch (want %x, have %x", want, have)
+ }
+ r := NewReader(bytes.NewReader(b.Bytes()))
+ for _, want := range tt.entries {
+ have, err := r.Read()
+ if err != nil {
+ t.Fatalf("decoding error: %v", err)
+ }
+ if have.Type != want.Type {
+ t.Fatalf("decoded entry does type mismatch (want %v, got %v)", want.Type, have.Type)
+ }
+ if !bytes.Equal(have.Value, want.Value) {
+ t.Fatalf("decoded entry does not match (want %#x, got %#x)", want.Value, have.Value)
+ }
+ }
+ })
+ }
+}
+
+func TestDecode(t *testing.T) {
+ for i, tt := range []struct {
+ have string
+ err error
+ }{
+ { // basic valid decoding
+ have: "ffff000000000000",
+ },
+ { // basic invalid decoding
+ have: "ffff000000000001",
+ err: fmt.Errorf("reserved bytes are non-zero"),
+ },
+ { // no more entries to read, returns EOF
+ have: "",
+ err: io.EOF,
+ },
+ { // malformed type
+ have: "bad",
+ err: io.ErrUnexpectedEOF,
+ },
+ { // malformed length
+ have: "badbeef",
+ err: io.ErrUnexpectedEOF,
+ },
+ { // specified length longer than actual value
+ have: "beef010000000000",
+ err: io.ErrUnexpectedEOF,
+ },
+ } {
+ r := NewReader(bytes.NewReader(common.FromHex(tt.have)))
+ if tt.err != nil {
+ _, err := r.Read()
+ if err == nil && tt.err != nil {
+ t.Fatalf("test %d, expected error, got none", i)
+ }
+ if err != nil && tt.err == nil {
+ t.Fatalf("test %d, expected no error, got %v", i, err)
+ }
+ if err != nil && tt.err != nil && err.Error() != tt.err.Error() {
+ t.Fatalf("expected error %v, got %v", tt.err, err)
+ }
+ continue
+ }
+ }
+}
+
+func FuzzCodec(f *testing.F) {
+ f.Fuzz(func(t *testing.T, input []byte) {
+ r := NewReader(bytes.NewReader(input))
+ entry, err := r.Read()
+ if err != nil {
+ return
+ }
+ var (
+ b = bytes.NewBuffer(nil)
+ w = NewWriter(b)
+ )
+ w.Write(entry.Type, entry.Value)
+ output := b.Bytes()
+ // Only care about the input that was actually consumed
+ input = input[:r.offset]
+ if !bytes.Equal(input, output) {
+ t.Fatalf("decode-encode mismatch, input %#x output %#x", input, output)
+ }
+ })
+}
diff --git a/internal/era/era.go b/internal/era/era.go
new file mode 100644
index 0000000000..a0e701b7e0
--- /dev/null
+++ b/internal/era/era.go
@@ -0,0 +1,283 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "math/big"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/era/e2store"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/golang/snappy"
+)
+
+var (
+ TypeVersion uint16 = 0x3265
+ TypeCompressedHeader uint16 = 0x03
+ TypeCompressedBody uint16 = 0x04
+ TypeCompressedReceipts uint16 = 0x05
+ TypeTotalDifficulty uint16 = 0x06
+ TypeAccumulator uint16 = 0x07
+ TypeBlockIndex uint16 = 0x3266
+
+ MaxEra1Size = 8192
+)
+
+// Filename returns a recognizable Era1-formatted file name for the specified
+// epoch and network.
+func Filename(network string, epoch int, root common.Hash) string {
+ return fmt.Sprintf("%s-%05d-%s.era1", network, epoch, root.Hex()[2:10])
+}
+
+// ReadDir reads all the era1 files in a directory for a given network.
+// Format: --.era1
+func ReadDir(dir, network string) ([]string, error) {
+ entries, err := os.ReadDir(dir)
+ if err != nil {
+ return nil, fmt.Errorf("error reading directory %s: %w", dir, err)
+ }
+ var (
+ next = uint64(0)
+ eras []string
+ )
+ for _, entry := range entries {
+ if path.Ext(entry.Name()) != ".era1" {
+ continue
+ }
+ parts := strings.Split(entry.Name(), "-")
+ if len(parts) != 3 || parts[0] != network {
+ // invalid era1 filename, skip
+ continue
+ }
+ if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return nil, fmt.Errorf("malformed era1 filename: %s", entry.Name())
+ } else if epoch != next {
+ return nil, fmt.Errorf("missing epoch %d", next)
+ }
+ next += 1
+ eras = append(eras, entry.Name())
+ }
+ return eras, nil
+}
+
+type ReadAtSeekCloser interface {
+ io.ReaderAt
+ io.Seeker
+ io.Closer
+}
+
+// Era reads and Era1 file.
+type Era struct {
+ f ReadAtSeekCloser // backing era1 file
+ s *e2store.Reader // e2store reader over f
+ m metadata // start, count, length info
+ mu *sync.Mutex // lock for buf
+ buf [8]byte // buffer reading entry offsets
+}
+
+// From returns an Era backed by f.
+func From(f ReadAtSeekCloser) (*Era, error) {
+ m, err := readMetadata(f)
+ if err != nil {
+ return nil, err
+ }
+ return &Era{
+ f: f,
+ s: e2store.NewReader(f),
+ m: m,
+ mu: new(sync.Mutex),
+ }, nil
+}
+
+// Open returns an Era backed by the given filename.
+func Open(filename string) (*Era, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ return From(f)
+}
+
+func (e *Era) Close() error {
+ return e.f.Close()
+}
+
+func (e *Era) GetBlockByNumber(num uint64) (*types.Block, error) {
+ if e.m.start > num || e.m.start+e.m.count <= num {
+ return nil, fmt.Errorf("out-of-bounds")
+ }
+ off, err := e.readOffset(num)
+ if err != nil {
+ return nil, err
+ }
+ r, n, err := newSnappyReader(e.s, TypeCompressedHeader, off)
+ if err != nil {
+ return nil, err
+ }
+ var header types.Header
+ if err := rlp.Decode(r, &header); err != nil {
+ return nil, err
+ }
+ off += n
+ r, _, err = newSnappyReader(e.s, TypeCompressedBody, off)
+ if err != nil {
+ return nil, err
+ }
+ var body types.Body
+ if err := rlp.Decode(r, &body); err != nil {
+ return nil, err
+ }
+ return types.NewBlockWithHeader(&header).WithBody(body.Transactions, body.Uncles), nil
+}
+
+// Accumulator reads the accumulator entry in the Era1 file.
+func (e *Era) Accumulator() (common.Hash, error) {
+ entry, err := e.s.Find(TypeAccumulator)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ return common.BytesToHash(entry.Value), nil
+}
+
+// InitialTD returns initial total difficulty before the difficulty of the
+// first block of the Era1 is applied.
+func (e *Era) InitialTD() (*big.Int, error) {
+ var (
+ r io.Reader
+ header types.Header
+ rawTd []byte
+ n int64
+ off int64
+ err error
+ )
+
+ // Read first header.
+ if off, err = e.readOffset(e.m.start); err != nil {
+ return nil, err
+ }
+ if r, n, err = newSnappyReader(e.s, TypeCompressedHeader, off); err != nil {
+ return nil, err
+ }
+ if err := rlp.Decode(r, &header); err != nil {
+ return nil, err
+ }
+ off += n
+
+ // Skip over next two records.
+ for i := 0; i < 2; i++ {
+ length, err := e.s.LengthAt(off)
+ if err != nil {
+ return nil, err
+ }
+ off += length
+ }
+
+ // Read total difficulty after first block.
+ if r, _, err = e.s.ReaderAt(TypeTotalDifficulty, off); err != nil {
+ return nil, err
+ }
+ rawTd, err = io.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+ td := new(big.Int).SetBytes(reverseOrder(rawTd))
+ return td.Sub(td, header.Difficulty), nil
+}
+
+// Start returns the listed start block.
+func (e *Era) Start() uint64 {
+ return e.m.start
+}
+
+// Count returns the total number of blocks in the Era1.
+func (e *Era) Count() uint64 {
+ return e.m.count
+}
+
+// readOffset reads a specific block's offset from the block index. The value n
+// is the absolute block number desired.
+func (e *Era) readOffset(n uint64) (int64, error) {
+ var (
+ blockIndexRecordOffset = e.m.length - 24 - int64(e.m.count)*8 // skips start, count, and header
+ firstIndex = blockIndexRecordOffset + 16 // first index after header / start-num
+ indexOffset = int64(n-e.m.start) * 8 // desired index * size of indexes
+ offOffset = firstIndex + indexOffset // offset of block offset
+ )
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ clearBuffer(e.buf[:])
+ if _, err := e.f.ReadAt(e.buf[:], offOffset); err != nil {
+ return 0, err
+ }
+ // Since the block offset is relative from the start of the block index record
+ // we need to add the record offset to it's offset to get the block's absolute
+ // offset.
+ return blockIndexRecordOffset + int64(binary.LittleEndian.Uint64(e.buf[:])), nil
+}
+
+// newReader returns a snappy.Reader for the e2store entry value at off.
+func newSnappyReader(e *e2store.Reader, expectedType uint16, off int64) (io.Reader, int64, error) {
+ r, n, err := e.ReaderAt(expectedType, off)
+ if err != nil {
+ return nil, 0, err
+ }
+ return snappy.NewReader(r), int64(n), err
+}
+
+// clearBuffer zeroes out the buffer.
+func clearBuffer(buf []byte) {
+ for i := 0; i < len(buf); i++ {
+ buf[i] = 0
+ }
+}
+
+// metadata wraps the metadata in the block index.
+type metadata struct {
+ start uint64
+ count uint64
+ length int64
+}
+
+// readMetadata reads the metadata stored in an Era1 file's block index.
+func readMetadata(f ReadAtSeekCloser) (m metadata, err error) {
+ // Determine length of reader.
+ if m.length, err = f.Seek(0, io.SeekEnd); err != nil {
+ return
+ }
+ b := make([]byte, 16)
+ // Read count. It's the last 8 bytes of the file.
+ if _, err = f.ReadAt(b[:8], m.length-8); err != nil {
+ return
+ }
+ m.count = binary.LittleEndian.Uint64(b)
+ // Read start. It's at the offset -sizeof(m.count) -
+ // count*sizeof(indexEntry) - sizeof(m.start)
+ if _, err = f.ReadAt(b[8:], m.length-16-int64(m.count*8)); err != nil {
+ return
+ }
+ m.start = binary.LittleEndian.Uint64(b[8:])
+ return
+}
diff --git a/internal/era/era_test.go b/internal/era/era_test.go
new file mode 100644
index 0000000000..ee5d9e82a0
--- /dev/null
+++ b/internal/era/era_test.go
@@ -0,0 +1,142 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "bytes"
+ "io"
+ "math/big"
+ "os"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+type testchain struct {
+ headers [][]byte
+ bodies [][]byte
+ receipts [][]byte
+ tds []*big.Int
+}
+
+func TestEra1Builder(t *testing.T) {
+ // Get temp directory.
+ f, err := os.CreateTemp("", "era1-test")
+ if err != nil {
+ t.Fatalf("error creating temp file: %v", err)
+ }
+ defer f.Close()
+
+ var (
+ builder = NewBuilder(f)
+ chain = testchain{}
+ )
+ for i := 0; i < 128; i++ {
+ chain.headers = append(chain.headers, []byte{byte('h'), byte(i)})
+ chain.bodies = append(chain.bodies, []byte{byte('b'), byte(i)})
+ chain.receipts = append(chain.receipts, []byte{byte('r'), byte(i)})
+ chain.tds = append(chain.tds, big.NewInt(int64(i)))
+ }
+
+ // Write blocks to Era1.
+ for i := 0; i < len(chain.headers); i++ {
+ var (
+ header = chain.headers[i]
+ body = chain.bodies[i]
+ receipts = chain.receipts[i]
+ hash = common.Hash{byte(i)}
+ td = chain.tds[i]
+ )
+ if err = builder.AddRLP(header, body, receipts, uint64(i), hash, td, big.NewInt(1)); err != nil {
+ t.Fatalf("error adding entry: %v", err)
+ }
+ }
+
+ // Finalize Era1.
+ if _, err := builder.Finalize(); err != nil {
+ t.Fatalf("error finalizing era1: %v", err)
+ }
+
+ // Verify Era1 contents.
+ e, err := Open(f.Name())
+ if err != nil {
+ t.Fatalf("failed to open era: %v", err)
+ }
+ it, err := NewRawIterator(e)
+ if err != nil {
+ t.Fatalf("failed to make iterator: %s", err)
+ }
+ for i := uint64(0); i < uint64(len(chain.headers)); i++ {
+ if !it.Next() {
+ t.Fatalf("expected more entries")
+ }
+ if it.Error() != nil {
+ t.Fatalf("unexpected error %v", it.Error())
+ }
+ // Check headers.
+ header, err := io.ReadAll(it.Header)
+ if err != nil {
+ t.Fatalf("error reading header: %v", err)
+ }
+ if !bytes.Equal(header, chain.headers[i]) {
+ t.Fatalf("mismatched header: want %s, got %s", chain.headers[i], header)
+ }
+ // Check bodies.
+ body, err := io.ReadAll(it.Body)
+ if err != nil {
+ t.Fatalf("error reading body: %v", err)
+ }
+ if !bytes.Equal(body, chain.bodies[i]) {
+ t.Fatalf("mismatched body: want %s, got %s", chain.bodies[i], body)
+ }
+ // Check receipts.
+ receipts, err := io.ReadAll(it.Receipts)
+ if err != nil {
+ t.Fatalf("error reading receipts: %v", err)
+ }
+ if !bytes.Equal(receipts, chain.receipts[i]) {
+ t.Fatalf("mismatched receipts: want %s, got %s", chain.receipts[i], receipts)
+ }
+
+ // Check total difficulty.
+ rawTd, err := io.ReadAll(it.TotalDifficulty)
+ if err != nil {
+ t.Fatalf("error reading td: %v", err)
+ }
+ td := new(big.Int).SetBytes(reverseOrder(rawTd))
+ if td.Cmp(chain.tds[i]) != 0 {
+ t.Fatalf("mismatched tds: want %s, got %s", chain.tds[i], td)
+ }
+ }
+}
+
+func TestEraFilename(t *testing.T) {
+ for i, tt := range []struct {
+ network string
+ epoch int
+ root common.Hash
+ expected string
+ }{
+ {"mainnet", 1, common.Hash{1}, "mainnet-00001-01000000.era1"},
+ {"goerli", 99999, common.HexToHash("0xdeadbeef00000000000000000000000000000000000000000000000000000000"), "goerli-99999-deadbeef.era1"},
+ } {
+ got := Filename(tt.network, tt.epoch, tt.root)
+ if tt.expected != got {
+ t.Errorf("test %d: invalid filename: want %s, got %s", i, tt.expected, got)
+ }
+ }
+}
diff --git a/internal/era/iterator.go b/internal/era/iterator.go
new file mode 100644
index 0000000000..e74a8154b1
--- /dev/null
+++ b/internal/era/iterator.go
@@ -0,0 +1,197 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "fmt"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Iterator wraps RawIterator and returns decoded Era1 entries.
+type Iterator struct {
+ inner *RawIterator
+}
+
+// NewRawIterator returns a new Iterator instance. Next must be immediately
+// called on new iterators to load the first item.
+func NewIterator(e *Era) (*Iterator, error) {
+ inner, err := NewRawIterator(e)
+ if err != nil {
+ return nil, err
+ }
+ return &Iterator{inner}, nil
+}
+
+// Next moves the iterator to the next block entry. It returns false when all
+// items have been read or an error has halted its progress. Block, Receipts,
+// and BlockAndReceipts should no longer be called after false is returned.
+func (it *Iterator) Next() bool {
+ return it.inner.Next()
+}
+
+// Number returns the current number block the iterator will return.
+func (it *Iterator) Number() uint64 {
+ return it.inner.next - 1
+}
+
+// Error returns the error status of the iterator. It should be called before
+// reading from any of the iterator's values.
+func (it *Iterator) Error() error {
+ return it.inner.Error()
+}
+
+// Block returns the block for the iterator's current position.
+func (it *Iterator) Block() (*types.Block, error) {
+ if it.inner.Header == nil || it.inner.Body == nil {
+ return nil, fmt.Errorf("header and body must be non-nil")
+ }
+ var (
+ header types.Header
+ body types.Body
+ )
+ if err := rlp.Decode(it.inner.Header, &header); err != nil {
+ return nil, err
+ }
+ if err := rlp.Decode(it.inner.Body, &body); err != nil {
+ return nil, err
+ }
+ return types.NewBlockWithHeader(&header).WithBody(body.Transactions, body.Uncles), nil
+}
+
+// Receipts returns the receipts for the iterator's current position.
+func (it *Iterator) Receipts() (types.Receipts, error) {
+ if it.inner.Receipts == nil {
+ return nil, fmt.Errorf("receipts must be non-nil")
+ }
+ var receipts types.Receipts
+ err := rlp.Decode(it.inner.Receipts, &receipts)
+ return receipts, err
+}
+
+// BlockAndReceipts returns the block and receipts for the iterator's current
+// position.
+func (it *Iterator) BlockAndReceipts() (*types.Block, types.Receipts, error) {
+ b, err := it.Block()
+ if err != nil {
+ return nil, nil, err
+ }
+ r, err := it.Receipts()
+ if err != nil {
+ return nil, nil, err
+ }
+ return b, r, nil
+}
+
+// TotalDifficulty returns the total difficulty for the iterator's current
+// position.
+func (it *Iterator) TotalDifficulty() (*big.Int, error) {
+ td, err := io.ReadAll(it.inner.TotalDifficulty)
+ if err != nil {
+ return nil, err
+ }
+ return new(big.Int).SetBytes(reverseOrder(td)), nil
+}
+
+// RawIterator reads an RLP-encode Era1 entries.
+type RawIterator struct {
+ e *Era // backing Era1
+ next uint64 // next block to read
+ err error // last error
+
+ Header io.Reader
+ Body io.Reader
+ Receipts io.Reader
+ TotalDifficulty io.Reader
+}
+
+// NewRawIterator returns a new RawIterator instance. Next must be immediately
+// called on new iterators to load the first item.
+func NewRawIterator(e *Era) (*RawIterator, error) {
+ return &RawIterator{
+ e: e,
+ next: e.m.start,
+ }, nil
+}
+
+// Next moves the iterator to the next block entry. It returns false when all
+// items have been read or an error has halted its progress. Header, Body,
+// Receipts, TotalDifficulty will be set to nil in the case returning false or
+// finding an error and should therefore no longer be read from.
+func (it *RawIterator) Next() bool {
+ // Clear old errors.
+ it.err = nil
+ if it.e.m.start+it.e.m.count <= it.next {
+ it.clear()
+ return false
+ }
+ off, err := it.e.readOffset(it.next)
+ if err != nil {
+ // Error here means block index is corrupted, so don't
+ // continue.
+ it.clear()
+ it.err = err
+ return false
+ }
+ var n int64
+ if it.Header, n, it.err = newSnappyReader(it.e.s, TypeCompressedHeader, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.Body, n, it.err = newSnappyReader(it.e.s, TypeCompressedBody, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.Receipts, n, it.err = newSnappyReader(it.e.s, TypeCompressedReceipts, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.TotalDifficulty, _, it.err = it.e.s.ReaderAt(TypeTotalDifficulty, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ it.next += 1
+ return true
+}
+
+// Number returns the current number block the iterator will return.
+func (it *RawIterator) Number() uint64 {
+ return it.next - 1
+}
+
+// Error returns the error status of the iterator. It should be called before
+// reading from any of the iterator's values.
+func (it *RawIterator) Error() error {
+ if it.err == io.EOF {
+ return nil
+ }
+ return it.err
+}
+
+// clear sets all the outputs to nil.
+func (it *RawIterator) clear() {
+ it.Header = nil
+ it.Body = nil
+ it.Receipts = nil
+ it.TotalDifficulty = nil
+}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 03f13af417..d84e410f2e 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -30,7 +30,6 @@ import (
"github.com/tyler-smith/go-bip39"
"github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/common"
@@ -53,12 +52,15 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// estimateGasErrorRatio is the amount of overestimation eth_estimateGas is
// allowed to produce in order to speed up calculations.
const estimateGasErrorRatio = 0.015
+var errBlobTxNotSupported = errors.New("signing blob transactions not supported")
+
// EthereumAPI provides an API to access Ethereum related information.
type EthereumAPI struct {
b Backend
@@ -142,26 +144,28 @@ func (s *EthereumAPI) Syncing() (interface{}, error) {
progress := s.b.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return false, nil
}
// Otherwise gather the block sync stats
return map[string]interface{}{
- "startingBlock": hexutil.Uint64(progress.StartingBlock),
- "currentBlock": hexutil.Uint64(progress.CurrentBlock),
- "highestBlock": hexutil.Uint64(progress.HighestBlock),
- "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
- "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
- "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
- "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
- "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
- "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
- "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
- "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
- "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
- "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
- "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
- "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "startingBlock": hexutil.Uint64(progress.StartingBlock),
+ "currentBlock": hexutil.Uint64(progress.CurrentBlock),
+ "highestBlock": hexutil.Uint64(progress.HighestBlock),
+ "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
+ "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
+ "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
+ "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
+ "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
+ "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
+ "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
+ "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
+ "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
+ "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
+ "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
+ "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "txIndexFinishedBlocks": hexutil.Uint64(progress.TxIndexFinishedBlocks),
+ "txIndexRemainingBlocks": hexutil.Uint64(progress.TxIndexRemainingBlocks),
}, nil
}
@@ -303,7 +307,7 @@ type PersonalAccountAPI struct {
b Backend
}
-// NewPersonalAccountAPI create a new PersonalAccountAPI.
+// NewPersonalAccountAPI creates a new PersonalAccountAPI.
func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI {
return &PersonalAccountAPI{
am: b.AccountManager(),
@@ -487,7 +491,7 @@ func (s *PersonalAccountAPI) signTransaction(ctx context.Context, args *Transact
return nil, err
}
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, s.b, false); err != nil {
return nil, err
}
// Assemble the transaction and sign with the wallet
@@ -506,7 +510,9 @@ func (s *PersonalAccountAPI) SendTransaction(ctx context.Context, args Transacti
s.nonceLock.LockAddr(args.from())
defer s.nonceLock.UnlockAddr(args.from())
}
-
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
+ }
signed, err := s.signTransaction(ctx, &args, passwd)
if err != nil {
log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
@@ -534,7 +540,9 @@ func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args Transacti
if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) {
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
-
+ if args.IsEIP4844() {
+ return nil, errBlobTxNotSupported
+ }
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
@@ -566,7 +574,7 @@ func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args Transacti
//
// The key used to calculate the signature is decrypted with the given password.
//
-// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
+// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-sign
func (s *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: addr}
@@ -596,7 +604,7 @@ func (s *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be 27 or 28 for legacy reasons.
//
-// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
+// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-ecrecover
func (s *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != crypto.SignatureLength {
return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)
@@ -781,11 +789,11 @@ func (s *BlockChainAPI) GetBalance(ctx context.Context, address common.Address,
if state == nil || err != nil {
return nil, err
}
-
- return (*hexutil.Big)(state.GetBalance(address)), state.Error()
+ b := state.GetBalance(address).ToBig()
+ return (*hexutil.Big)(b), state.Error()
}
-// Result structs for GetProof
+// AccountResult structs for GetProof
type AccountResult struct {
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
@@ -880,10 +888,11 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
return nil, err
}
+ balance := statedb.GetBalance(address).ToBig()
return &AccountResult{
Address: address,
AccountProof: accountProof,
- Balance: (*hexutil.Big)(statedb.GetBalance(address)),
+ Balance: (*hexutil.Big)(balance),
CodeHash: codeHash,
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
StorageHash: storageRoot,
@@ -1143,7 +1152,8 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
}
// Override account balance.
if account.Balance != nil {
- state.SetBalance(addr, (*big.Int)(*account.Balance))
+ u256Balance, _ := uint256.FromBig((*big.Int)(*account.Balance))
+ state.SetBalance(addr, u256Balance)
}
if account.State != nil && account.StateDiff != nil {
@@ -1272,14 +1282,14 @@ func doCallWithState(ctx context.Context, b Backend, args TransactionArgs, heade
defer cancel()
// Get a new instance of the EVM.
- msg, err := args.ToMessage(globalGasCap, header.BaseFee)
- if err != nil {
- return nil, err
- }
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if blockOverrides != nil {
blockOverrides.Apply(&blockCtx)
}
+ msg, err := args.ToMessage(globalGasCap, blockCtx.BaseFee)
+ if err != nil {
+ return nil, err
+ }
evm := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
// Wait for the context to be done and cancel the evm. Even if the
@@ -1338,38 +1348,6 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap)
}
-func newRevertError(revert []byte) *revertError {
- err := vm.ErrExecutionReverted
-
- reason, errUnpack := abi.UnpackRevert(revert)
- if errUnpack == nil {
- err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason)
- }
-
- return &revertError{
- error: err,
- reason: hexutil.Encode(revert),
- }
-}
-
-// revertError is an API error that encompasses an EVM revertal with JSON error
-// code and a binary data blob.
-type revertError struct {
- error
- reason string // revert reason hex encoded
-}
-
-// ErrorCode returns the JSON error code for a revertal.
-// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
-func (e *revertError) ErrorCode() int {
- return 3
-}
-
-// ErrorData returns the hex encoded revert reason.
-func (e *revertError) ErrorData() interface{} {
- return e.reason
-}
-
// Call executes the given transaction on the state for the given block number.
//
// Additionally, the caller can specify a batch of contract for fields overriding.
@@ -1448,6 +1426,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
// returns error if the transaction would revert or if there are unexpected failures. The returned
// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
// configuration (if non-zero).
+// Note: Required blob gas is not computed in this method.
func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
@@ -1814,7 +1793,7 @@ type accessListResult struct {
// CreateAccessList creates an EIP-2930 type AccessList for the given transaction.
// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
func (s *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
+ bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
@@ -1841,14 +1820,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
if db == nil || err != nil {
return nil, 0, nil, err
}
- // If the gas amount is not set, default to RPC gas cap.
- if args.Gas == nil {
- tmp := hexutil.Uint64(b.RPCGasCap())
- args.Gas = &tmp
- }
// Ensure any missing fields are filled, extract the recipient and input data
- if err := args.setDefaults(ctx, b); err != nil {
+ if err := args.setDefaults(ctx, b, true); err != nil {
return nil, 0, nil, err
}
@@ -2023,10 +1997,18 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H
borTx := false
// Try to return an already finalized transaction
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
+ found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ // No finalized transaction, try to retrieve it from the pool
+ if tx := s.b.GetPoolTransaction(hash); tx != nil {
+ return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
+ }
+ if err == nil {
+ return nil, nil
+ }
+ return nil, NewTxIndexingError()
}
+
// fetch bor block tx if necessary
if tx == nil {
if tx, blockHash, blockNumber, index, err = s.b.GetBorBlockTransaction(ctx, hash); err != nil {
@@ -2065,30 +2047,31 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func (s *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
-
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = s.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+
+ return nil, NewTxIndexingError()
}
- // Serialize to RLP and return
return tx.MarshalBinary()
}
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
+
borTx := false
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
if err != nil {
- // When the transaction doesn't exist, the RPC method should return JSON null
- // as per specification.
- return nil, nil
+ return nil, NewTxIndexingError() // transaction is not fully indexed
+ }
+ if !found {
+ return nil, nil // transaction is not existent or reachable
}
if tx == nil {
tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(s.b.ChainDb(), hash)
@@ -2247,9 +2230,12 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
s.nonceLock.LockAddr(args.from())
defer s.nonceLock.UnlockAddr(args.from())
}
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
+ }
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, s.b, false); err != nil {
return common.Hash{}, err
}
// Assemble the transaction and sign with the wallet
@@ -2267,8 +2253,10 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
// on a given unsigned transaction, and returns it to the caller for further
// processing (signing + broadcast).
func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
+ args.blobSidecarAllowed = true
+
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, s.b, false); err != nil {
return nil, err
}
// Assemble the transaction and obtain rlp
@@ -2337,11 +2325,13 @@ func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionAr
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
+ if args.IsEIP4844() {
+ return nil, errBlobTxNotSupported
+ }
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
-
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, s.b, false); err != nil {
return nil, err
}
// Before actually sign the transaction, ensure the transaction fee is reasonable.
@@ -2399,8 +2389,7 @@ func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, g
if sendArgs.Nonce == nil {
return common.Hash{}, errors.New("missing transaction nonce in transaction spec")
}
-
- if err := sendArgs.setDefaults(ctx, s.b); err != nil {
+ if err := sendArgs.setDefaults(ctx, s.b, false); err != nil {
return common.Hash{}, err
}
@@ -2551,16 +2540,15 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
// GetRawTransaction returns the bytes of the transaction for the given hash.
func (s *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
-
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = s.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+ return nil, NewTxIndexingError()
}
return tx.MarshalBinary()
diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go
index 082032f54a..ccdb794097 100644
--- a/internal/ethapi/api_test.go
+++ b/internal/ethapi/api_test.go
@@ -17,8 +17,10 @@
package ethapi
import (
+ "bytes"
"context"
"crypto/ecdsa"
+ "crypto/sha256"
"encoding/json"
"errors"
"fmt"
@@ -31,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
@@ -43,6 +46,7 @@ import (
"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/crypto/kzg4844"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/blocktest"
@@ -403,10 +407,30 @@ func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData {
}
}
+func newTestAccountManager(t *testing.T) (*accounts.Manager, accounts.Account) {
+ var (
+ dir = t.TempDir()
+ am = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true})
+ b = keystore.NewKeyStore(dir, 2, 1)
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ )
+ acc, err := b.ImportECDSA(testKey, "")
+ if err != nil {
+ t.Fatalf("failed to create test account: %v", err)
+ }
+ if err := b.Unlock(acc, ""); err != nil {
+ t.Fatalf("failed to unlock account: %v\n", err)
+ }
+ am.AddBackend(b)
+ return am, acc
+}
+
type testBackend struct {
db ethdb.Database
chain *core.BlockChain
pending *types.Block
+ accman *accounts.Manager
+ acc accounts.Account
}
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {
@@ -419,6 +443,8 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
TrieDirtyDisabled: true, // Archive mode
}
)
+ accman, acc := newTestAccountManager(t)
+ gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)}
// Generate blocks for testing
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
txlookupLimit := uint64(0)
@@ -430,7 +456,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}
- backend := &testBackend{db: db, chain: chain}
+ backend := &testBackend{db: db, chain: chain, accman: accman, acc: acc}
return backend
}
@@ -446,7 +472,7 @@ func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBloc
return nil, nil, nil, nil, nil
}
func (b testBackend) ChainDb() ethdb.Database { return b.db }
-func (b testBackend) AccountManager() *accounts.Manager { return nil }
+func (b testBackend) AccountManager() *accounts.Manager { return b.accman }
func (b testBackend) ExtRPCEnabled() bool { return false }
func (b testBackend) RPCGasCap() uint64 { return 10000000 }
func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
@@ -559,14 +585,14 @@ func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) even
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
-func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
- return tx, blockHash, blockNumber, index, nil
+ return true, tx, blockHash, blockNumber, index, nil
}
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
- panic("implement me")
+ return 0, nil
}
func (b testBackend) Stats() (pending int, queued int) { panic("implement me") }
func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
@@ -676,8 +702,8 @@ func TestEstimateGas(t *testing.T) {
var (
accounts = newAccounts(2)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
},
@@ -686,12 +712,13 @@ func TestEstimateGas(t *testing.T) {
signer = types.HomesteadSigner{}
randomAccounts = newAccounts(2)
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
var testSuite = []struct {
blockNumber rpc.BlockNumber
@@ -791,6 +818,18 @@ func TestEstimateGas(t *testing.T) {
expectErr: nil,
want: 67595,
},
+ // Blobs should have no effect on gas estimate
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ To: &accounts[1].addr,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ },
+ want: 21000,
+ },
}
for i, tc := range testSuite {
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides)
@@ -820,8 +859,8 @@ func TestCall(t *testing.T) {
var (
accounts = newAccounts(3)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -830,12 +869,13 @@ func TestCall(t *testing.T) {
genBlocks = 10
signer = types.HomesteadSigner{}
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
randomAccounts := newAccounts(3)
var testSuite = []struct {
@@ -957,6 +997,32 @@ func TestCall(t *testing.T) {
blockOverrides: BlockOverrides{Number: (*hexutil.Big)(big.NewInt(11))},
want: "0x000000000000000000000000000000000000000000000000000000000000000b",
},
+ // Invalid blob tx
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[1].addr,
+ Input: &hexutil.Bytes{0x00},
+ BlobHashes: []common.Hash{},
+ },
+ expectErr: core.ErrBlobTxCreate,
+ },
+ // BLOBHASH opcode
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[1].addr,
+ To: &randomAccounts[2].addr,
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ },
+ overrides: StateOverride{
+ randomAccounts[2].addr: {
+ Code: hex2Bytes("60004960005260206000f3"),
+ },
+ },
+ want: "0x0122000000000000000000000000000000000000000000000000000000000000",
+ },
}
for i, tc := range testSuite {
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
@@ -983,6 +1049,323 @@ func TestCall(t *testing.T) {
}
}
+func TestSignTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ res, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v\n", err)
+ }
+ tx, err := json.Marshal(res.Tx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expect := `{"type":"0x2","chainId":"0x1","nonce":"0x0","to":"0x703c4b2bd70c169f5717101caee543299fc946c7","gas":"0x5208","gasPrice":null,"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x684ee180","value":"0x1","input":"0x","accessList":[],"v":"0x0","r":"0x8fabeb142d585dd9247f459f7e6fe77e2520c88d50ba5d220da1533cea8b34e1","s":"0x582dd68b21aef36ba23f34e49607329c20d981d30404daf749077f5606785ce7","yParity":"0x0","hash":"0x93927839207cfbec395da84b8a2bc38b7b65d2cb2819e9fef1f091f5b1d4cc8f"}`
+ if !bytes.Equal(tx, []byte(expect)) {
+ t.Errorf("result mismatch. Have:\n%s\nWant:\n%s\n", tx, expect)
+ }
+}
+
+func TestSignBlobTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{{0x01, 0x22}},
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ _, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err == nil {
+ t.Fatalf("should fail on blob transaction")
+ }
+ if !errors.Is(err, errBlobTxNotSupported) {
+ t.Errorf("error mismatch. Have: %v, want: %v", err, errBlobTxNotSupported)
+ }
+}
+
+func TestSendBlobTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ _, err = api.SendTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err == nil {
+ t.Errorf("sending tx should have failed")
+ } else if !errors.Is(err, errBlobTxNotSupported) {
+ t.Errorf("unexpected error. Have %v, want %v\n", err, errBlobTxNotSupported)
+ }
+}
+
+func TestFillBlobTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ }
+ emptyBlob = kzg4844.Blob{}
+ emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
+ emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
+ emptyBlobHash common.Hash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ type result struct {
+ Hashes []common.Hash
+ Sidecar *types.BlobTxSidecar
+ }
+ suite := []struct {
+ name string
+ args TransactionArgs
+ err string
+ want *result
+ }{
+ {
+ name: "TestInvalidParamsCombination1",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{{}},
+ Proofs: []kzg4844.Proof{{}},
+ },
+ err: `blob proofs provided while commitments were not`,
+ },
+ {
+ name: "TestInvalidParamsCombination2",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{{}},
+ Commitments: []kzg4844.Commitment{{}},
+ },
+ err: `blob commitments provided while proofs were not`,
+ },
+ {
+ name: "TestInvalidParamsCount1",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{{}},
+ Commitments: []kzg4844.Commitment{{}, {}},
+ Proofs: []kzg4844.Proof{{}, {}},
+ },
+ err: `number of blobs and commitments mismatch (have=2, want=1)`,
+ },
+ {
+ name: "TestInvalidParamsCount2",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{{}, {}},
+ Commitments: []kzg4844.Commitment{{}, {}},
+ Proofs: []kzg4844.Proof{{}},
+ },
+ err: `number of blobs and proofs mismatch (have=1, want=2)`,
+ },
+ {
+ name: "TestInvalidProofVerification",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{{}, {}},
+ Commitments: []kzg4844.Commitment{{}, {}},
+ Proofs: []kzg4844.Proof{{}, {}},
+ },
+ err: `failed to verify blob proof: short buffer`,
+ },
+ {
+ name: "TestGenerateBlobHashes",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ want: &result{
+ Hashes: []common.Hash{emptyBlobHash},
+ Sidecar: &types.BlobTxSidecar{
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ },
+ },
+ {
+ name: "TestValidBlobHashes",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{emptyBlobHash},
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ want: &result{
+ Hashes: []common.Hash{emptyBlobHash},
+ Sidecar: &types.BlobTxSidecar{
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ },
+ },
+ {
+ name: "TestInvalidBlobHashes",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{{0x01, 0x22}},
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ err: fmt.Sprintf("blob hash verification failed (have=%s, want=%s)", common.Hash{0x01, 0x22}, emptyBlobHash),
+ },
+ {
+ name: "TestGenerateBlobProofs",
+ args: TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ Blobs: []kzg4844.Blob{emptyBlob},
+ },
+ want: &result{
+ Hashes: []common.Hash{emptyBlobHash},
+ Sidecar: &types.BlobTxSidecar{
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
+ },
+ },
+ }
+ for _, tc := range suite {
+ t.Run(tc.name, func(t *testing.T) {
+ res, err := api.FillTransaction(context.Background(), tc.args)
+ if len(tc.err) > 0 {
+ if err == nil {
+ t.Fatalf("missing error. want: %s", tc.err)
+ } else if err != nil && err.Error() != tc.err {
+ t.Fatalf("error mismatch. want: %s, have: %s", tc.err, err.Error())
+ }
+ return
+ }
+ if err != nil && len(tc.err) == 0 {
+ t.Fatalf("expected no error. have: %s", err)
+ }
+ if res == nil {
+ t.Fatal("result missing")
+ }
+ want, err := json.Marshal(tc.want)
+ if err != nil {
+ t.Fatalf("failed to encode expected: %v", err)
+ }
+ have, err := json.Marshal(result{Hashes: res.Tx.BlobHashes(), Sidecar: res.Tx.BlobTxSidecar()})
+ if err != nil {
+ t.Fatalf("failed to encode computed sidecar: %v", err)
+ }
+ if !bytes.Equal(have, want) {
+ t.Errorf("blob sidecar mismatch. Have: %s, want: %s", have, want)
+ }
+ })
+ }
+}
+
+func argsFromTransaction(tx *types.Transaction, from common.Address) TransactionArgs {
+ var (
+ gas = tx.Gas()
+ nonce = tx.Nonce()
+ input = tx.Data()
+ )
+ return TransactionArgs{
+ From: &from,
+ To: tx.To(),
+ Gas: (*hexutil.Uint64)(&gas),
+ MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()),
+ MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()),
+ Value: (*hexutil.Big)(tx.Value()),
+ Nonce: (*hexutil.Uint64)(&nonce),
+ Input: (*hexutil.Bytes)(&input),
+ ChainID: (*hexutil.Big)(tx.ChainId()),
+ // TODO: impl accessList conversion
+ //AccessList: tx.AccessList(),
+ BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()),
+ BlobHashes: tx.BlobHashes(),
+ }
+}
+
type account struct {
key *ecdsa.PrivateKey
addr common.Address
@@ -1228,7 +1611,7 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
genesis = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
},
@@ -1472,7 +1855,8 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
}
func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) {
- config := *params.TestChainConfig
+ config := *params.MergedTestChainConfig
+
config.ShanghaiBlock = big.NewInt(0)
config.CancunBlock = big.NewInt(0)
@@ -1486,7 +1870,7 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
Config: &config,
ExcessBlobGas: new(uint64),
BlobGasUsed: new(uint64),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
// // SPDX-License-Identifier: GPL-3.0
@@ -1506,14 +1890,12 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
txHashes = make([]common.Hash, genBlocks)
)
- // Set the terminal total difficulty in the config
- genesis.Config.TerminalTotalDifficulty = big.NewInt(0)
- genesis.Config.TerminalTotalDifficultyPassed = true
backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
var (
tx *types.Transaction
err error
)
+ b.SetPoS()
switch i {
case 0:
// transfer 1000wei
@@ -1562,7 +1944,6 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
b.AddTx(tx)
txHashes[i] = tx.Hash()
}
- b.SetPoS()
})
return backend, txHashes
}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 59facc5108..765080d3da 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -76,7 +76,7 @@ type Backend interface {
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go
new file mode 100644
index 0000000000..b5e668a805
--- /dev/null
+++ b/internal/ethapi/errors.go
@@ -0,0 +1,78 @@
+// Copyright 2024 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 ethapi
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/vm"
+)
+
+// revertError is an API error that encompasses an EVM revert with JSON error
+// code and a binary data blob.
+type revertError struct {
+ error
+ reason string // revert reason hex encoded
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *revertError) ErrorCode() int {
+ return 3
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *revertError) ErrorData() interface{} {
+ return e.reason
+}
+
+// newRevertError creates a revertError instance with the provided revert data.
+func newRevertError(revert []byte) *revertError {
+ err := vm.ErrExecutionReverted
+
+ reason, errUnpack := abi.UnpackRevert(revert)
+ if errUnpack == nil {
+ err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason)
+ }
+ return &revertError{
+ error: err,
+ reason: hexutil.Encode(revert),
+ }
+}
+
+// TxIndexingError is an API error that indicates the transaction indexing is not
+// fully finished yet with JSON error code and a binary data blob.
+type TxIndexingError struct{}
+
+// NewTxIndexingError creates a TxIndexingError instance.
+func NewTxIndexingError() *TxIndexingError { return &TxIndexingError{} }
+
+// Error implement error interface, returning the error message.
+func (e *TxIndexingError) Error() string {
+ return "transaction indexing is in progress"
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *TxIndexingError) ErrorCode() int {
+ return -32000 // to be decided
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *TxIndexingError) ErrorData() interface{} { return "transaction indexing is in progress" }
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json
index 759dbf69e9..d2bdbacd73 100644
--- a/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json
@@ -4,7 +4,7 @@
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -14,7 +14,7 @@
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x200",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactions": [],
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json b/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json
index 759dbf69e9..d2bdbacd73 100644
--- a/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json
@@ -4,7 +4,7 @@
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -14,7 +14,7 @@
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x200",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactions": [],
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json
index dc61aa9a2e..1bd68888b6 100644
--- a/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json
@@ -4,7 +4,7 @@
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -13,7 +13,7 @@
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json b/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json
index dc61aa9a2e..1bd68888b6 100644
--- a/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json
@@ -4,7 +4,7 @@
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -13,7 +13,7 @@
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index 0408bc2690..4eb6a7a325 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -19,6 +19,7 @@ package ethapi
import (
"bytes"
"context"
+ "crypto/sha256"
"errors"
"fmt"
"math/big"
@@ -26,10 +27,18 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
+)
+
+var (
+ maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
)
// TransactionArgs represents the arguments to construct a new transaction
@@ -53,6 +62,18 @@ type TransactionArgs struct {
// Introduced by AccessListTxType transaction.
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
+
+ // For BlobTxType
+ BlobFeeCap *hexutil.Big `json:"maxFeePerBlobGas"`
+ BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
+
+ // For BlobTxType transactions with blob sidecar
+ Blobs []kzg4844.Blob `json:"blobs"`
+ Commitments []kzg4844.Commitment `json:"commitments"`
+ Proofs []kzg4844.Proof `json:"proofs"`
+
+ // This configures whether blobs are allowed to be passed.
+ blobSidecarAllowed bool
}
// from retrieves the transaction sender address.
@@ -78,7 +99,10 @@ func (args *TransactionArgs) data() []byte {
}
// setDefaults fills in default values for unspecified tx fields.
-func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
+func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGasEstimation bool) error {
+ if err := args.setBlobTxSidecar(ctx, b); err != nil {
+ return err
+ }
if err := args.setFeeDefaults(ctx, b); err != nil {
return err
}
@@ -100,35 +124,59 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
}
- if args.To == nil && len(args.data()) == 0 {
- return errors.New(`contract creation without any data provided`)
+ // BlobTx fields
+ if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
+ return errors.New(`need at least 1 blob for a blob transaction`)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) > maxBlobsPerTransaction {
+ return fmt.Errorf(`too many blobs in transaction (have=%d, max=%d)`, len(args.BlobHashes), maxBlobsPerTransaction)
+ }
+
+ // create check
+ if args.To == nil {
+ if args.BlobHashes != nil {
+ return errors.New(`missing "to" in blob transaction`)
+ }
+ if len(args.data()) == 0 {
+ return errors.New(`contract creation without any data provided`)
+ }
}
- // Estimate the gas usage if necessary.
if args.Gas == nil {
- // These fields are immutable during the estimation, safe to
- // pass the pointer directly.
- data := args.data()
- callArgs := TransactionArgs{
- From: args.From,
- To: args.To,
- GasPrice: args.GasPrice,
- MaxFeePerGas: args.MaxFeePerGas,
- MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
- Value: args.Value,
- Data: (*hexutil.Bytes)(&data),
- AccessList: args.AccessList,
- }
+ if skipGasEstimation { // Skip gas usage estimation if a precise gas limit is not critical, e.g., in non-transaction calls.
+ gas := hexutil.Uint64(b.RPCGasCap())
+ if gas == 0 {
+ gas = hexutil.Uint64(math.MaxUint64 / 2)
+ }
+ args.Gas = &gas
+ } else { // Estimate the gas usage otherwise.
+ // These fields are immutable during the estimation, safe to
+ // pass the pointer directly.
+ data := args.data()
+ callArgs := TransactionArgs{
+ From: args.From,
+ To: args.To,
+ GasPrice: args.GasPrice,
+ MaxFeePerGas: args.MaxFeePerGas,
+ MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
+ Value: args.Value,
+ Data: (*hexutil.Bytes)(&data),
+ AccessList: args.AccessList,
+ BlobFeeCap: args.BlobFeeCap,
+ BlobHashes: args.BlobHashes,
+ }
- pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
- estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, b.RPCGasCap())
- if err != nil {
- return err
- }
+ latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
+ estimated, err := DoEstimateGas(ctx, b, callArgs, latestBlockNr, nil, b.RPCGasCap())
+ if err != nil {
+ return err
+ }
- args.Gas = &estimated
- log.Trace("Estimate gas usage automatically", "gas", args.Gas)
+ args.Gas = &estimated
+ log.Trace("Estimate gas usage automatically", "gas", args.Gas)
+ }
}
+
// If chain id is provided, ensure it matches the local chain id. Otherwise, set the local
// chain id as the default.
want := b.ChainConfig().ChainID
@@ -145,25 +193,46 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
// setFeeDefaults fills in default fee values for unspecified tx fields.
func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) error {
+ head := b.CurrentHeader()
+ // Sanity check the EIP-4844 fee parameters.
+ if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerBlobGas, if specified, must be non-zero")
+ }
+ if err := args.setCancunFeeDefaults(ctx, head, b); err != nil {
+ return err
+ }
// If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
- // If the tx has completely specified a fee mechanism, no default is needed. This allows users
- // who are not yet synced past London to get defaults for other tx values. See
- // https://github.com/ethereum/go-ethereum/pull/23274 for more information.
+ // If the tx has completely specified a fee mechanism, no default is needed.
+ // This allows users who are not yet synced past London to get defaults for
+ // other tx values. See https://github.com/ethereum/go-ethereum/pull/23274
+ // for more information.
eip1559ParamsSet := args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil
- if (args.GasPrice != nil && !eip1559ParamsSet) || (args.GasPrice == nil && eip1559ParamsSet) {
- // Sanity check the EIP-1559 fee parameters if present.
- if args.GasPrice == nil && args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
+ // Sanity check the EIP-1559 fee parameters if present.
+ if args.GasPrice == nil && eip1559ParamsSet {
+ if args.MaxFeePerGas.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerGas must be non-zero")
+ }
+ if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
-
- return nil
+ return nil // No need to set anything, user already set MaxFeePerGas and MaxPriorityFeePerGas
}
+
+ // Sanity check the non-EIP-1559 fee parameters.
+ isLondon := b.ChainConfig().IsLondon(head.Number)
+ if args.GasPrice != nil && !eip1559ParamsSet {
+ // Zero gas-price is not allowed after London fork
+ if args.GasPrice.ToInt().Sign() == 0 && isLondon {
+ return errors.New("gasPrice must be non-zero after london fork")
+ }
+ return nil // No need to set anything, user already set GasPrice
+ }
+
// Now attempt to fill in default value depending on whether London is active or not.
- head := b.CurrentHeader()
- if b.ChainConfig().IsLondon(head.Number) {
+ if isLondon {
// London is active, set maxPriorityFeePerGas and maxFeePerGas.
if err := args.setLondonFeeDefaults(ctx, head, b); err != nil {
return err
@@ -184,6 +253,25 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
return nil
}
+// setCancunFeeDefaults fills in reasonable default fee values for unspecified fields.
+func (args *TransactionArgs) setCancunFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
+ // Set maxFeePerBlobGas if it is missing.
+ if args.BlobHashes != nil && args.BlobFeeCap == nil {
+ var excessBlobGas uint64
+ if head.ExcessBlobGas != nil {
+ excessBlobGas = *head.ExcessBlobGas
+ }
+ // ExcessBlobGas must be set for a Cancun block.
+ blobBaseFee := eip4844.CalcBlobFee(excessBlobGas)
+ // Set the max fee to be 2 times larger than the previous block's blob base fee.
+ // The additional slack allows the tx to not become invalidated if the base
+ // fee is rising.
+ val := new(big.Int).Mul(blobBaseFee, big.NewInt(2))
+ args.BlobFeeCap = (*hexutil.Big)(val)
+ }
+ return nil
+}
+
// setLondonFeeDefaults fills in reasonable default fee values for unspecified fields.
func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
// Set maxPriorityFeePerGas if it is missing.
@@ -214,6 +302,81 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ
return nil
}
+// setBlobTxSidecar adds the blob tx
+func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context, b Backend) error {
+ // No blobs, we're done.
+ if args.Blobs == nil {
+ return nil
+ }
+
+ // Passing blobs is not allowed in all contexts, only in specific methods.
+ if !args.blobSidecarAllowed {
+ return errors.New(`"blobs" is not supported for this RPC method`)
+ }
+
+ n := len(args.Blobs)
+ // Assume user provides either only blobs (w/o hashes), or
+ // blobs together with commitments and proofs.
+ if args.Commitments == nil && args.Proofs != nil {
+ return errors.New(`blob proofs provided while commitments were not`)
+ } else if args.Commitments != nil && args.Proofs == nil {
+ return errors.New(`blob commitments provided while proofs were not`)
+ }
+
+ // len(blobs) == len(commitments) == len(proofs) == len(hashes)
+ if args.Commitments != nil && len(args.Commitments) != n {
+ return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
+ }
+ if args.Proofs != nil && len(args.Proofs) != n {
+ return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), n)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) != n {
+ return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
+ }
+
+ if args.Commitments == nil {
+ // Generate commitment and proof.
+ commitments := make([]kzg4844.Commitment, n)
+ proofs := make([]kzg4844.Proof, n)
+ for i, b := range args.Blobs {
+ c, err := kzg4844.BlobToCommitment(b)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
+ }
+ commitments[i] = c
+ p, err := kzg4844.ComputeBlobProof(b, c)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
+ }
+ proofs[i] = p
+ }
+ args.Commitments = commitments
+ args.Proofs = proofs
+ } else {
+ for i, b := range args.Blobs {
+ if err := kzg4844.VerifyBlobProof(b, args.Commitments[i], args.Proofs[i]); err != nil {
+ return fmt.Errorf("failed to verify blob proof: %v", err)
+ }
+ }
+ }
+
+ hashes := make([]common.Hash, n)
+ hasher := sha256.New()
+ for i, c := range args.Commitments {
+ hashes[i] = kzg4844.CalcBlobHashV1(hasher, &c)
+ }
+ if args.BlobHashes != nil {
+ for i, h := range hashes {
+ if h != args.BlobHashes[i] {
+ return fmt.Errorf("blob hash verification failed (have=%s, want=%s)", args.BlobHashes[i], h)
+ }
+ }
+ } else {
+ args.BlobHashes = hashes
+ }
+ return nil
+}
+
// ToMessage converts the transaction arguments to the Message type used by the
// core evm. This method is used in calls and traces that do not require a real
// live transaction.
@@ -245,9 +408,10 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
}
var (
- gasPrice *big.Int
- gasFeeCap *big.Int
- gasTipCap *big.Int
+ gasPrice *big.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ blobFeeCap *big.Int
)
if baseFee == nil {
@@ -287,6 +451,11 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
}
}
+ if args.BlobFeeCap != nil {
+ blobFeeCap = args.BlobFeeCap.ToInt()
+ } else if args.BlobHashes != nil {
+ blobFeeCap = new(big.Int)
+ }
value := new(big.Int)
if args.Value != nil {
value = args.Value.ToInt()
@@ -309,6 +478,8 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
GasTipCap: gasTipCap,
Data: data,
AccessList: accessList,
+ BlobGasFeeCap: blobFeeCap,
+ BlobHashes: args.BlobHashes,
SkipAccountChecks: true,
}
@@ -321,6 +492,32 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
var data types.TxData
switch {
+ case args.BlobHashes != nil:
+ al := types.AccessList{}
+ if args.AccessList != nil {
+ al = *args.AccessList
+ }
+ data = &types.BlobTx{
+ To: *args.To,
+ ChainID: uint256.MustFromBig((*big.Int)(args.ChainID)),
+ Nonce: uint64(*args.Nonce),
+ Gas: uint64(*args.Gas),
+ GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),
+ GasTipCap: uint256.MustFromBig((*big.Int)(args.MaxPriorityFeePerGas)),
+ Value: uint256.MustFromBig((*big.Int)(args.Value)),
+ Data: args.data(),
+ AccessList: al,
+ BlobHashes: args.BlobHashes,
+ BlobFeeCap: uint256.MustFromBig((*big.Int)(args.BlobFeeCap)),
+ }
+ if args.Blobs != nil {
+ data.(*types.BlobTx).Sidecar = &types.BlobTxSidecar{
+ Blobs: args.Blobs,
+ Commitments: args.Commitments,
+ Proofs: args.Proofs,
+ }
+ }
+
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
@@ -338,6 +535,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
Data: args.data(),
AccessList: al,
}
+
case args.AccessList != nil:
data = &types.AccessListTx{
To: args.To,
@@ -349,6 +547,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
Data: args.data(),
AccessList: *args.AccessList,
}
+
default:
data = &types.LegacyTx{
To: args.To,
@@ -363,8 +562,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
return types.NewTx(data)
}
-// ToTransaction converts the arguments to a transaction.
-// This assumes that setDefaults has been called.
-func (args *TransactionArgs) ToTransaction() *types.Transaction {
- return args.toTransaction()
+// IsEIP4844 returns an indicator if the args contains EIP4844 fields.
+func (args *TransactionArgs) IsEIP4844() bool {
+ return args.BlobHashes != nil || args.BlobFeeCap != nil
}
diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go
index d7cba3c50d..f32ed90962 100644
--- a/internal/ethapi/transaction_args_test.go
+++ b/internal/ethapi/transaction_args_test.go
@@ -45,15 +45,16 @@ func TestSetFeeDefaults(t *testing.T) {
t.Parallel()
type test struct {
- name string
- isLondon bool
- in *TransactionArgs
- want *TransactionArgs
- err error
+ name string
+ fork string // options: legacy, london, cancun
+ in *TransactionArgs
+ want *TransactionArgs
+ err error
}
var (
b = newBackendMock()
+ zero = (*hexutil.Big)(big.NewInt(0))
fortytwo = (*hexutil.Big)(big.NewInt(42))
maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
@@ -63,51 +64,65 @@ func TestSetFeeDefaults(t *testing.T) {
// Legacy txs
{
"legacy tx pre-London",
- false,
+ "legacy",
&TransactionArgs{},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx pre-London with zero price",
+ "legacy",
+ &TransactionArgs{GasPrice: zero},
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ },
{
"legacy tx post-London, explicit gas price",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx post-London with zero price",
+ "london",
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ errors.New("gasPrice must be non-zero after london fork"),
+ },
// Access list txs
{
"access list tx pre-London",
- false,
+ "legacy",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London, explicit gas price",
- false,
+ "legacy",
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London",
- true,
+ "london",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
@@ -116,95 +131,127 @@ func TestSetFeeDefaults(t *testing.T) {
// Dynamic fee txs
{
"dynamic tx post-London",
- true,
+ "london",
&TransactionArgs{},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic fee tx pre-London, maxFee set",
- false,
+ "legacy",
&TransactionArgs{MaxFeePerGas: maxFee},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx pre-London, priorityFee set",
- false,
+ "legacy",
&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx, maxFee < priorityFee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
nil,
errors.New("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
},
{
"dynamic fee tx, maxFee < priorityFee while setting default",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
nil,
errors.New("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
},
+ {
+ "dynamic fee tx post-London, explicit gas price",
+ "london",
+ &TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
+ nil,
+ errors.New("maxFeePerGas must be non-zero"),
+ },
// Misc
{
"set all fee parameters",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxPriorityFee",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxFee",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
+ // EIP-4844
+ {
+ "set gas price and maxFee for blob transaction",
+ "cancun",
+ &TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, BlobHashes: []common.Hash{}},
+ nil,
+ errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
+ },
+ {
+ "fill maxFeePerBlobGas",
+ "cancun",
+ &TransactionArgs{BlobHashes: []common.Hash{}},
+ &TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ nil,
+ },
+ {
+ "fill maxFeePerBlobGas when dynamic fees are set",
+ "cancun",
+ &TransactionArgs{BlobHashes: []common.Hash{}, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ &TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ nil,
+ },
}
ctx := context.Background()
for i, test := range tests {
- if test.isLondon {
- b.activateLondon()
- } else {
- b.deactivateLondon()
+ if err := b.setFork(test.fork); err != nil {
+ t.Fatalf("failed to set fork: %v", err)
}
got := test.in
err := got.setFeeDefaults(ctx, b)
- if err != nil && err.Error() == test.err.Error() {
- // Test threw expected error.
+ if err != nil {
+ if test.err == nil {
+ t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
+ } else if err.Error() != test.err.Error() {
+ t.Fatalf("test %d (%s): unexpected error: (got: %s, want: %s)", i, test.name, err, test.err)
+ }
+ // Matching error.
continue
- } else if err != nil {
- t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
+ } else if test.err != nil {
+ t.Fatalf("test %d (%s): expected error: %s", i, test.name, test.err)
}
if !reflect.DeepEqual(got, test.want) {
@@ -250,13 +297,25 @@ func newBackendMock() *backendMock {
}
}
-func (b *backendMock) activateLondon() {
- b.current.Number = big.NewInt(1100)
+func (b *backendMock) setFork(fork string) error {
+ if fork == "legacy" {
+ b.current.Number = big.NewInt(900)
+ b.current.Time = 555
+ } else if fork == "london" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 555
+ } else if fork == "cancun" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 700
+ // Blob base fee will be 2
+ excess := uint64(2314058)
+ b.current.ExcessBlobGas = &excess
+ } else {
+ return errors.New("invalid fork")
+ }
+ return nil
}
-func (b *backendMock) deactivateLondon() {
- b.current.Number = big.NewInt(900)
-}
func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(42), nil
}
@@ -335,8 +394,8 @@ func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) eve
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
-func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- return nil, [32]byte{}, 0, 0, nil
+func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ return false, nil, [32]byte{}, 0, 0, nil
}
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
diff --git a/internal/flags/categories.go b/internal/flags/categories.go
index 487684d98b..3ff0767921 100644
--- a/internal/flags/categories.go
+++ b/internal/flags/categories.go
@@ -35,6 +35,7 @@ const (
LoggingCategory = "LOGGING AND DEBUGGING"
MetricsCategory = "METRICS AND STATS"
MiscCategory = "MISC"
+ TestingCategory = "TESTING"
DeprecatedCategory = "ALIASED (deprecated)"
)
diff --git a/internal/flags/flags.go b/internal/flags/flags.go
index bff4a7ce64..56ba6447d1 100644
--- a/internal/flags/flags.go
+++ b/internal/flags/flags.go
@@ -265,7 +265,8 @@ type BigFlag struct {
Hidden bool
HasBeenSet bool
- Value *big.Int
+ Value *big.Int
+ defaultValue *big.Int
Aliases []string
EnvVars []string
@@ -278,6 +279,10 @@ func (f *BigFlag) IsSet() bool { return f.HasBeenSet }
func (f *BigFlag) String() string { return cli.FlagStringer(f) }
func (f *BigFlag) Apply(set *flag.FlagSet) error {
+ // Set default value so that environment wont be able to overwrite it
+ if f.Value != nil {
+ f.defaultValue = new(big.Int).Set(f.Value)
+ }
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
@@ -292,7 +297,6 @@ func (f *BigFlag) Apply(set *flag.FlagSet) error {
f.Value = new(big.Int)
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
})
-
return nil
}
@@ -319,8 +323,7 @@ func (f *BigFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
-
- return f.GetValue()
+ return f.defaultValue.String()
}
// bigValue turns *big.Int into a flag.Value
diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go
index c9aa729041..e505c905ae 100644
--- a/internal/flags/helpers.go
+++ b/internal/flags/helpers.go
@@ -42,7 +42,7 @@ func NewApp(usage string) *cli.App {
app.EnableBashCompletion = true
app.Version = params.VersionWithCommit(git.Commit, git.Date)
app.Usage = usage
- app.Copyright = "Copyright 2013-2023 The go-ethereum Authors"
+ app.Copyright = "Copyright 2013-2024 The go-ethereum Authors"
app.Before = func(ctx *cli.Context) error {
MigrateGlobalFlags(ctx)
return nil
diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js
index 7e6ae09d50..8144850343 100644
--- a/internal/jsre/deps/web3.js
+++ b/internal/jsre/deps/web3.js
@@ -3961,6 +3961,8 @@ var outputSyncingFormatter = function(result) {
result.healedBytecodeBytes = utils.toDecimal(result.healedBytecodeBytes);
result.healingTrienodes = utils.toDecimal(result.healingTrienodes);
result.healingBytecode = utils.toDecimal(result.healingBytecode);
+ result.txIndexFinishedBlocks = utils.toDecimal(result.txIndexFinishedBlocks);
+ result.txIndexRemainingBlocks = utils.toDecimal(result.txIndexRemainingBlocks);
return result;
};
diff --git a/internal/testrand/rand.go b/internal/testrand/rand.go
new file mode 100644
index 0000000000..690993de05
--- /dev/null
+++ b/internal/testrand/rand.go
@@ -0,0 +1,53 @@
+// Copyright 2023 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 testrand
+
+import (
+ crand "crypto/rand"
+ "encoding/binary"
+ mrand "math/rand"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// prng is a pseudo random number generator seeded by strong randomness.
+// The randomness is printed on startup in order to make failures reproducible.
+var prng = initRand()
+
+func initRand() *mrand.Rand {
+ var seed [8]byte
+ crand.Read(seed[:])
+ rnd := mrand.New(mrand.NewSource(int64(binary.LittleEndian.Uint64(seed[:]))))
+ return rnd
+}
+
+// Bytes generates a random byte slice with specified length.
+func Bytes(n int) []byte {
+ r := make([]byte, n)
+ prng.Read(r)
+ return r
+}
+
+// Hash generates a random hash.
+func Hash() common.Hash {
+ return common.BytesToHash(Bytes(common.HashLength))
+}
+
+// Address generates a random address.
+func Address() common.Address {
+ return common.BytesToAddress(Bytes(common.AddressLength))
+}
diff --git a/internal/utesting/utesting.go b/internal/utesting/utesting.go
index 6520dfc564..83d79c45b2 100644
--- a/internal/utesting/utesting.go
+++ b/internal/utesting/utesting.go
@@ -35,6 +35,7 @@ import (
type Test struct {
Name string
Fn func(*T)
+ Slow bool
}
// Result is the result of a test execution.
diff --git a/log/handler_glog.go b/log/handler_glog.go
index fb1e03c5b5..f51bae2a4a 100644
--- a/log/handler_glog.go
+++ b/log/handler_glog.go
@@ -192,7 +192,7 @@ func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
frame, _ := fs.Next()
for _, rule := range h.patterns {
- if rule.pattern.MatchString(fmt.Sprintf("%+s", frame.File)) {
+ if rule.pattern.MatchString(fmt.Sprintf("+%s", frame.File)) {
h.siteCache[r.PC], lvl, ok = rule.level, rule.level, true
}
}
diff --git a/log/logger.go b/log/logger.go
index 93d62f080b..75e3643044 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -83,7 +83,7 @@ func LevelAlignedString(l slog.Level) string {
}
}
-// LevelString returns a 5-character string containing the name of a Lvl.
+// LevelString returns a string containing the name of a Lvl.
func LevelString(l slog.Level) string {
switch l {
case LevelTrace:
@@ -95,7 +95,7 @@ func LevelString(l slog.Level) string {
case slog.LevelWarn:
return "warn"
case slog.LevelError:
- return "eror"
+ return "error"
case LevelCrit:
return "crit"
default:
diff --git a/log/logger_test.go b/log/logger_test.go
index a633f5ad7a..ff981fd018 100644
--- a/log/logger_test.go
+++ b/log/logger_test.go
@@ -2,6 +2,7 @@ package log
import (
"bytes"
+ "errors"
"fmt"
"io"
"math/big"
@@ -77,7 +78,7 @@ func benchmarkLogger(b *testing.B, l Logger) {
tt = time.Now()
bigint = big.NewInt(100)
nilbig *big.Int
- err = fmt.Errorf("Oh nooes it's crap")
+ err = errors.New("Oh nooes it's crap")
)
b.ReportAllocs()
b.ResetTimer()
@@ -106,7 +107,7 @@ func TestLoggerOutput(t *testing.T) {
tt = time.Time{}
bigint = big.NewInt(100)
nilbig *big.Int
- err = fmt.Errorf("Oh nooes it's crap")
+ err = errors.New("Oh nooes it's crap")
smallUint = uint256.NewInt(500_000)
bigUint = &uint256.Int{0xff, 0xff, 0xff, 0xff}
)
diff --git a/log/root.go b/log/root.go
index 71040fff47..8662d87063 100644
--- a/log/root.go
+++ b/log/root.go
@@ -10,8 +10,7 @@ import (
var root atomic.Value
func init() {
- defaultLogger := &logger{slog.New(DiscardHandler())}
- SetDefault(defaultLogger)
+ root.Store(&logger{slog.New(DiscardHandler())})
}
// SetDefault sets the default global logger
diff --git a/metrics/counter.go b/metrics/counter.go
index 25e895f023..6ec60d25af 100644
--- a/metrics/counter.go
+++ b/metrics/counter.go
@@ -8,7 +8,7 @@ type CounterSnapshot interface {
Count() int64
}
-// Counters hold an int64 value that can be incremented and decremented.
+// Counter hold an int64 value that can be incremented and decremented.
type Counter interface {
Clear()
Dec(int64)
diff --git a/metrics/gauge.go b/metrics/gauge.go
index c480ec5a05..d6edf59e53 100644
--- a/metrics/gauge.go
+++ b/metrics/gauge.go
@@ -2,12 +2,12 @@ package metrics
import "sync/atomic"
-// gaugeSnapshot contains a readonly int64.
+// GaugeSnapshot contains a readonly int64.
type GaugeSnapshot interface {
Value() int64
}
-// Gauges hold an int64 value that can be set arbitrarily.
+// Gauge holds an int64 value that can be set arbitrarily.
type Gauge interface {
Snapshot() GaugeSnapshot
Update(int64)
@@ -79,7 +79,7 @@ func (g *StandardGauge) Update(v int64) {
g.value.Store(v)
}
-// Update updates the gauge's value if v is larger then the current valie.
+// Update updates the gauge's value if v is larger then the current value.
func (g *StandardGauge) UpdateIfGt(v int64) {
for {
exist := g.value.Load()
diff --git a/metrics/gauge_float64.go b/metrics/gauge_float64.go
index eef6d7673e..5a6e9c1f6b 100644
--- a/metrics/gauge_float64.go
+++ b/metrics/gauge_float64.go
@@ -53,7 +53,7 @@ type gaugeFloat64Snapshot float64
// Value returns the value at the time the snapshot was taken.
func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }
-// NilGauge is a no-op Gauge.
+// NilGaugeFloat64 is a no-op Gauge.
type NilGaugeFloat64 struct{}
func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} }
diff --git a/metrics/gauge_info.go b/metrics/gauge_info.go
index c44b2d85f3..0010edc324 100644
--- a/metrics/gauge_info.go
+++ b/metrics/gauge_info.go
@@ -9,7 +9,7 @@ type GaugeInfoSnapshot interface {
Value() GaugeInfoValue
}
-// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily.
+// GaugeInfo holds a GaugeInfoValue value that can be set arbitrarily.
type GaugeInfo interface {
Update(GaugeInfoValue)
Snapshot() GaugeInfoSnapshot
diff --git a/metrics/healthcheck.go b/metrics/healthcheck.go
index 05b6ff01ab..67e0e25f20 100644
--- a/metrics/healthcheck.go
+++ b/metrics/healthcheck.go
@@ -1,6 +1,6 @@
package metrics
-// Healthchecks hold an error value describing an arbitrary up/down status.
+// Healthcheck holds an error value describing an arbitrary up/down status.
type Healthcheck interface {
Check()
Error() error
diff --git a/metrics/histogram.go b/metrics/histogram.go
index 395891f7e7..7badbfd097 100644
--- a/metrics/histogram.go
+++ b/metrics/histogram.go
@@ -4,7 +4,7 @@ type HistogramSnapshot interface {
SampleSnapshot
}
-// Histograms calculate distribution statistics from a series of int64 values.
+// Histogram calculates distribution statistics from a series of int64 values.
type Histogram interface {
Clear()
Update(int64)
diff --git a/metrics/influxdb/influxdbv2.go b/metrics/influxdb/influxdbv2.go
index 49714b395f..1e8a8b8318 100644
--- a/metrics/influxdb/influxdbv2.go
+++ b/metrics/influxdb/influxdbv2.go
@@ -25,7 +25,7 @@ type v2Reporter struct {
write api.WriteAPI
}
-// InfluxDBWithTags starts a InfluxDB reporter which will post the from the given metrics.Registry at each d interval with the specified tags
+// InfluxDBV2WithTags starts a InfluxDB reporter which will post the from the given metrics.Registry at each d interval with the specified tags
func InfluxDBV2WithTags(r metrics.Registry, d time.Duration, endpoint string, token string, bucket string, organization string, namespace string, tags map[string]string) {
rep := &v2Reporter{
reg: r,
diff --git a/miner/fake_miner.go b/miner/fake_miner.go
index 7c835ee2df..b5583f9fa0 100644
--- a/miner/fake_miner.go
+++ b/miner/fake_miner.go
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
type DefaultBorMiner struct {
@@ -93,7 +94,7 @@ func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, he
blockchain := &testBlockChainBor{chainConfig, statedb, 10000000, new(event.Feed)}
pool := legacypool.New(testTxPoolConfigBor, blockchain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfigBor.PriceLimit), blockchain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(testTxPoolConfigBor.PriceLimit, blockchain, []txpool.SubPool{pool})
backend := NewMockBackendBor(bc, txpool)
@@ -132,7 +133,7 @@ func NewDBForFakes(t TensingObject) (ethdb.Database, *core.Genesis, *params.Chai
addr := common.HexToAddress("12345")
genesis := core.DeveloperGenesisBlock(11_500_000, &addr)
- chainConfig, _, err := core.SetupGenesisBlock(chainDB, trie.NewDatabase(chainDB, trie.HashDefaults), genesis)
+ chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb.NewDatabase(chainDB, triedb.HashDefaults), genesis)
if err != nil {
t.Fatalf("can't create new chain config: %v", err)
}
diff --git a/miner/ordering.go b/miner/ordering.go
index 828d53d241..b5400be99a 100644
--- a/miner/ordering.go
+++ b/miner/ordering.go
@@ -21,28 +21,31 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
)
// txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap
type txWithMinerFee struct {
tx *txpool.LazyTransaction
from common.Address
- fees *big.Int
+ fees *uint256.Int
}
// newTxWithMinerFee creates a wrapped transaction, calculating the effective
// miner gasTipCap if a base fee is provided.
// Returns error in case of a negative effective miner gasTipCap.
-func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *big.Int) (*txWithMinerFee, error) {
- tip := new(big.Int).Set(tx.GasTipCap)
+func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *uint256.Int) (*txWithMinerFee, error) {
+ tip := new(uint256.Int).Set(tx.GasTipCap)
if baseFee != nil {
if tx.GasFeeCap.Cmp(baseFee) < 0 {
return nil, types.ErrGasFeeCapTooLow
}
- tip = math.BigMin(tx.GasTipCap, new(big.Int).Sub(tx.GasFeeCap, baseFee))
+ tip = new(uint256.Int).Sub(tx.GasFeeCap, baseFee)
+ if tip.Gt(tx.GasTipCap) {
+ tip = tx.GasTipCap
+ }
}
return &txWithMinerFee{
tx: tx,
@@ -87,7 +90,7 @@ type transactionsByPriceAndNonce struct {
txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions
heads txByPriceAndTime // Next transaction for each unique account (price heap)
signer types.Signer // Signer for the set of transactions
- baseFee *big.Int // Current base fee
+ baseFee *uint256.Int // Current base fee
}
// newTransactionsByPriceAndNonce creates a transaction set that can retrieve
@@ -96,10 +99,15 @@ type transactionsByPriceAndNonce struct {
// Note, the input map is reowned so the caller should not interact any more with
// if after providing it to the constructor.
func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce {
+ // Convert the basefee from header format to uint256 format
+ var baseFeeUint *uint256.Int
+ if baseFee != nil {
+ baseFeeUint = uint256.MustFromBig(baseFee)
+ }
// Initialize a price and received time based heap with the head transactions
heads := make(txByPriceAndTime, 0, len(txs))
for from, accTxs := range txs {
- wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFee)
+ wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFeeUint)
if err != nil {
delete(txs, from)
continue
@@ -114,12 +122,12 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
txs: txs,
heads: heads,
signer: signer,
- baseFee: baseFee,
+ baseFee: baseFeeUint,
}
}
// Peek returns the next transaction by price.
-func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *big.Int) {
+func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *uint256.Int) {
if len(t.heads) == 0 {
return nil, nil
}
@@ -149,3 +157,14 @@ func (t *transactionsByPriceAndNonce) GetTxs() int {
func (t *transactionsByPriceAndNonce) Pop() {
heap.Pop(&t.heads)
}
+
+// Empty returns if the price heap is empty. It can be used to check it simpler
+// than calling peek and checking for nil return.
+func (t *transactionsByPriceAndNonce) Empty() bool {
+ return len(t.heads) == 0
+}
+
+// Clear removes the entire content of the heap.
+func (t *transactionsByPriceAndNonce) Clear() {
+ t.heads, t.txs = nil, nil
+}
diff --git a/miner/ordering_test.go b/miner/ordering_test.go
index d2de9b9f34..3587a835c8 100644
--- a/miner/ordering_test.go
+++ b/miner/ordering_test.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/holiman/uint256"
)
func TestTransactionPriceNonceSortLegacy(t *testing.T) {
@@ -92,8 +93,8 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
@@ -160,8 +161,8 @@ func TestTransactionTimeSort(t *testing.T) {
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
diff --git a/miner/payload_building.go b/miner/payload_building.go
index 0b12728652..fe4b56f2e7 100644
--- a/miner/payload_building.go
+++ b/miner/payload_building.go
@@ -35,12 +35,13 @@ import (
// Check engine-api specification for more details.
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
type BuildPayloadArgs struct {
- Parent common.Hash // The parent block to build payload on top
- Timestamp uint64 // The provided timestamp of generated payload
- FeeRecipient common.Address // The provided recipient address for collecting transaction fee
- Random common.Hash // The provided randomness value
- Withdrawals types.Withdrawals // The provided withdrawals
- BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
+ Parent common.Hash // The parent block to build payload on top
+ Timestamp uint64 // The provided timestamp of generated payload
+ FeeRecipient common.Address // The provided recipient address for collecting transaction fee
+ Random common.Hash // The provided randomness value
+ Withdrawals types.Withdrawals // The provided withdrawals
+ BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
+ Version engine.PayloadVersion // Versioning byte for payload id calculation.
}
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
@@ -58,7 +59,7 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
var out engine.PayloadID
copy(out[:], hasher.Sum(nil)[:8])
-
+ out[0] = byte(args.Version)
return out
}
diff --git a/miner/stress/clique/main.go b/miner/stress/clique/main.go
index 6fdde7745f..2692762184 100644
--- a/miner/stress/clique/main.go
+++ b/miner/stress/clique/main.go
@@ -163,9 +163,9 @@ func makeGenesis(faucets []*ecdsa.PrivateKey, sealers []*ecdsa.PrivateKey) *core
genesis.Config.ChainID = big.NewInt(18)
genesis.Config.Clique.Period = 1
- genesis.Alloc = core.GenesisAlloc{}
+ genesis.Alloc = types.GenesisAlloc{}
for _, faucet := range faucets {
- genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{
+ genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = types.Account{
Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil),
}
}
diff --git a/miner/test_backend.go b/miner/test_backend.go
index 035acce037..231b215512 100644
--- a/miner/test_backend.go
+++ b/miner/test_backend.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
- "math/big"
"os"
"sync"
"sync/atomic"
@@ -168,15 +167,15 @@ func (w *worker) mainLoopWithDelay(ctx context.Context, delay uint, opcodeDelay
Hash: tx.Hash(),
Tx: nil, // Do *not* set this! We need to resolve it later to pull blobs in
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.NewInt(tx.GasFeeCap().Uint64()),
+ GasTipCap: uint256.NewInt(tx.GasTipCap().Uint64()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
}
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
tcount := w.current.tcount
- w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
+ w.commitTransactions(w.current, txset, nil, nil, context.Background())
// Only update the snapshot if any new transactons were added
// to the pending block
@@ -322,7 +321,7 @@ func (w *worker) fillTransactionsWithDelay(ctx context.Context, interrupt *atomi
// Split the pending transactions into locals and remotes
// Fill the block with all available pending transactions.
- pending := w.eth.TxPool().Pending(true)
+ pending := w.eth.TxPool().Pending(txpool.PendingFilter{})
localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending
var (
@@ -394,7 +393,7 @@ func (w *worker) fillTransactionsWithDelay(ctx context.Context, interrupt *atomi
tracing.Exec(ctx, "", "worker.SplittingTransactions", func(ctx context.Context, span trace.Span) {
prePendingTime := time.Now()
- pending := w.eth.TxPool().Pending(true)
+ pending := w.eth.TxPool().Pending(txpool.PendingFilter{})
remoteTxs = pending
postPendingTime := time.Now()
diff --git a/miner/worker.go b/miner/worker.go
index 536ff80156..c39f20c5cd 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -37,11 +37,11 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/ethereum/go-ethereum/common"
- cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/tracing"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/bor"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/blockstm"
"github.com/ethereum/go-ethereum/core/state"
@@ -237,7 +237,7 @@ type worker struct {
mu sync.RWMutex // The lock used to protect the coinbase and extra fields
coinbase common.Address
extra []byte
- tip *big.Int // Minimum tip needed for non-local transaction to include them
+ tip *uint256.Int // Minimum tip needed for non-local transaction to include them
pendingMu sync.RWMutex
pendingTasks map[common.Hash]*task
@@ -296,7 +296,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
isLocalBlock: isLocalBlock,
coinbase: config.Etherbase,
extra: config.ExtraData,
- tip: config.GasPrice,
+ tip: uint256.MustFromBig(config.GasPrice),
pendingTasks: make(map[common.Hash]*task),
txsCh: make(chan core.NewTxsEvent, txChanSize),
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
@@ -401,7 +401,7 @@ func (w *worker) setExtra(extra []byte) {
func (w *worker) setGasTip(tip *big.Int) {
w.mu.Lock()
defer w.mu.Unlock()
- w.tip = tip
+ w.tip = uint256.MustFromBig(tip)
}
// setRecommitInterval updates the interval for miner sealing work recommitting.
@@ -649,15 +649,18 @@ func (w *worker) mainLoop(ctx context.Context) {
Hash: tx.Hash(),
Tx: nil, // Do *not* set this! We need to resolve it later to pull blobs in
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
}
- txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
+ plainTxs := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) // Mixed bag of everrything, yolo
+ blobTxs := newTransactionsByPriceAndNonce(w.current.signer, nil, w.current.header.BaseFee) // Empty bag, don't bother optimising
+
tcount := w.current.tcount
- w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
+
+ w.commitTransactions(w.current, plainTxs, blobTxs, nil, context.Background())
// Only update the snapshot if any new transactons were added
// to the pending block
@@ -917,7 +920,7 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction, inte
return receipt.Logs, nil
}
-func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32, minTip *big.Int, interruptCtx context.Context) error {
+func (w *worker) commitTransactions(env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32, interruptCtx context.Context) error {
gasLimit := env.header.GasLimit
if env.gasPool == nil {
env.gasPool = new(core.GasPool).AddGas(gasLimit)
@@ -985,8 +988,34 @@ mainloop:
log.Trace("Not enough gas for further transactions", "have", env.gasPool, "want", params.TxGas)
break
}
+ // If we don't have enough blob space for any further blob transactions,
+ // skip that list altogether
+ if !blobTxs.Empty() && env.blobs*params.BlobTxBlobGasPerBlob >= params.MaxBlobGasPerBlock {
+ log.Trace("Not enough blob space for further blob transactions")
+ blobTxs.Clear()
+ // Fall though to pick up any plain txs
+ }
// Retrieve the next transaction and abort if all done.
- ltx, tip := txs.Peek()
+
+ var (
+ ltx *txpool.LazyTransaction
+ txs *transactionsByPriceAndNonce
+ )
+ pltx, ptip := plainTxs.Peek()
+ bltx, btip := blobTxs.Peek()
+
+ switch {
+ case pltx == nil:
+ txs, ltx = blobTxs, bltx
+ case bltx == nil:
+ txs, ltx = plainTxs, pltx
+ default:
+ if ptip.Lt(btip) {
+ txs, ltx = blobTxs, bltx
+ } else {
+ txs, ltx = plainTxs, pltx
+ }
+ }
if ltx == nil {
break
}
@@ -1001,11 +1030,7 @@ mainloop:
txs.Pop()
continue
}
- // If we don't receive enough tip for the next transaction, skip the account
- if tip.Cmp(minTip) < 0 {
- log.Trace("Not enough tip for transaction", "hash", ltx.Hash, "tip", tip, "needed", minTip)
- break // If the next-best is too low, surely no better will be available
- }
+
// Transaction seems to fit, pull it up from the pool
tx := ltx.Resolve()
if tx == nil {
@@ -1343,20 +1368,31 @@ func startProfiler(profile string, filepath string, number uint64) (func() error
// fillTransactions retrieves the pending transactions from the txpool and fills them
// into the given sealing block. The transaction selection and ordering strategy can
// be customized with the plugin in the future.
+
//
//nolint:gocognit
func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32, env *environment, interruptCtx context.Context) error {
ctx, span := tracing.StartSpan(ctx, "fillTransactions")
defer tracing.EndSpan(span)
- // Split the pending transactions into locals and remotes
- // Fill the block with all available pending transactions.
- pending := w.eth.TxPool().Pending(true)
- localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending
+ w.mu.RLock()
+ tip := w.tip
+ w.mu.RUnlock()
+
+ // Retrieve the pending transactions pre-filtered by the 1559/4844 dynamic fees
+ filter := txpool.PendingFilter{
+ MinTip: tip,
+ }
+ if env.header.BaseFee != nil {
+ filter.BaseFee = uint256.MustFromBig(env.header.BaseFee)
+ }
+ if env.header.ExcessBlobGas != nil {
+ filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(*env.header.ExcessBlobGas))
+ }
var (
- localTxsCount int
- remoteTxsCount int
+ localPlainTxsCount int
+ remotePlainTxsCount int
)
// TODO: move to config or RPC
@@ -1420,19 +1456,33 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
}(env.header.Number.Uint64())
}
+ var (
+ localPlainTxs, remotePlainTxs, localBlobTxs, remoteBlobTxs map[common.Address][]*txpool.LazyTransaction
+ )
+
tracing.Exec(ctx, "", "worker.SplittingTransactions", func(ctx context.Context, span trace.Span) {
prePendingTime := time.Now()
- pending := w.eth.TxPool().Pending(true)
- remoteTxs = pending
+ filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
+ pendingPlainTxs := w.eth.TxPool().Pending(filter)
+
+ filter.OnlyPlainTxs, filter.OnlyBlobTxs = false, true
+ pendingBlobTxs := w.eth.TxPool().Pending(filter)
+
+ // Split the pending transactions into locals and remotes.
+ localPlainTxs, remotePlainTxs = make(map[common.Address][]*txpool.LazyTransaction), pendingPlainTxs
+ localBlobTxs, remoteBlobTxs = make(map[common.Address][]*txpool.LazyTransaction), pendingBlobTxs
postPendingTime := time.Now()
for _, account := range w.eth.TxPool().Locals() {
- if txs := remoteTxs[account]; len(txs) > 0 {
- delete(remoteTxs, account)
-
- localTxs[account] = txs
+ if txs := remotePlainTxs[account]; len(txs) > 0 {
+ delete(remotePlainTxs, account)
+ localPlainTxs[account] = txs
+ }
+ if txs := remoteBlobTxs[account]; len(txs) > 0 {
+ delete(remoteBlobTxs, account)
+ localBlobTxs[account] = txs
}
}
@@ -1440,8 +1490,8 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
tracing.SetAttributes(
span,
- attribute.Int("len of local txs", localTxsCount),
- attribute.Int("len of remote txs", remoteTxsCount),
+ attribute.Int("len of local txs", localPlainTxsCount),
+ attribute.Int("len of remote txs", remotePlainTxsCount),
attribute.String("time taken by Pending()", fmt.Sprintf("%v", postPendingTime.Sub(prePendingTime))),
attribute.String("time taken by Locals()", fmt.Sprintf("%v", postLocalsTime.Sub(postPendingTime))),
)
@@ -1453,29 +1503,22 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
err error
)
- w.mu.RLock()
- tip := w.tip
- w.mu.RUnlock()
-
- if len(localTxs) > 0 {
- var txs *transactionsByPriceAndNonce
+ // Fill the block with all available pending transactions.
+ if len(localPlainTxs) > 0 || len(localBlobTxs) > 0 {
+ var plainTxs, blobTxs *transactionsByPriceAndNonce
tracing.Exec(ctx, "", "worker.LocalTransactionsByPriceAndNonce", func(ctx context.Context, span trace.Span) {
- var baseFee *uint256.Int
- if env.header.BaseFee != nil {
- baseFee = cmath.FromBig(env.header.BaseFee)
- }
-
- txs = newTransactionsByPriceAndNonce(env.signer, localTxs, baseFee.ToBig())
+ plainTxs = newTransactionsByPriceAndNonce(env.signer, localPlainTxs, env.header.BaseFee)
+ blobTxs = newTransactionsByPriceAndNonce(env.signer, localBlobTxs, env.header.BaseFee)
tracing.SetAttributes(
span,
- attribute.Int("len of tx local Heads", txs.GetTxs()),
+ attribute.Int("len of tx local Heads", plainTxs.GetTxs()),
)
})
tracing.Exec(ctx, "", "worker.LocalCommitTransactions", func(ctx context.Context, span trace.Span) {
- err = w.commitTransactions(env, txs, interrupt, new(big.Int), interruptCtx)
+ err = w.commitTransactions(env, plainTxs, blobTxs, interrupt, interruptCtx)
})
if err != nil {
@@ -1485,25 +1528,21 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
localEnvTCount = env.tcount
}
- if len(remoteTxs) > 0 {
- var txs *transactionsByPriceAndNonce
+ if len(remotePlainTxs) > 0 || len(remoteBlobTxs) > 0 {
+ var plainTxs, blobTxs *transactionsByPriceAndNonce
tracing.Exec(ctx, "", "worker.RemoteTransactionsByPriceAndNonce", func(ctx context.Context, span trace.Span) {
- var baseFee *uint256.Int
- if env.header.BaseFee != nil {
- baseFee = cmath.FromBig(env.header.BaseFee)
- }
-
- txs = newTransactionsByPriceAndNonce(env.signer, remoteTxs, baseFee.ToBig())
+ plainTxs = newTransactionsByPriceAndNonce(env.signer, remotePlainTxs, env.header.BaseFee)
+ blobTxs = newTransactionsByPriceAndNonce(env.signer, remoteBlobTxs, env.header.BaseFee)
tracing.SetAttributes(
span,
- attribute.Int("len of tx remote Heads", txs.GetTxs()),
+ attribute.Int("len of tx remote Heads", plainTxs.GetTxs()),
)
})
tracing.Exec(ctx, "", "worker.RemoteCommitTransactions", func(ctx context.Context, span trace.Span) {
- err = w.commitTransactions(env, txs, interrupt, tip, interruptCtx)
+ err = w.commitTransactions(env, plainTxs, blobTxs, interrupt, interruptCtx)
})
if err != nil {
diff --git a/miner/worker_test.go b/miner/worker_test.go
index cac3e936df..a6fc85ae9e 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -43,8 +43,9 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/golang/mock/gomock"
+ "github.com/holiman/uint256"
"gotest.tools/assert"
)
@@ -226,7 +227,7 @@ type testWorkerBackend struct {
func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database) *testWorkerBackend {
var gspec = &core.Genesis{
Config: chainConfig,
- Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
+ Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
}
switch e := engine.(type) {
case *bor.Bor:
@@ -251,7 +252,7 @@ func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engi
t.Fatalf("core.NewBlockChain failed: %v", err)
}
pool := legacypool.New(testTxPoolConfig, chain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), chain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, chain, []txpool.SubPool{pool})
return &testWorkerBackend{
db: db,
@@ -426,7 +427,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
taskCh := make(chan struct{}, 2)
checkEqual := func(t *testing.T, task *task) {
// The work should contain 1 tx
- receiptLen, balance := 1, big.NewInt(1000)
+ receiptLen, balance := 1, uint256.NewInt(1000)
if len(task.receipts) != receiptLen {
t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen)
}
@@ -970,7 +971,7 @@ func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) {
// This test chain imports the mined blocks.
db2 := rawdb.NewMemoryDatabase()
- back.genesis.MustCommit(db2, trie.NewDatabase(db2, trie.HashDefaults))
+ back.genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
chain, _ := core.NewParallelBlockChain(db2, nil, back.genesis, nil, engine, vm.Config{}, nil, nil, nil, 8)
defer chain.Stop()
diff --git a/node/defaults.go b/node/defaults.go
index d359522c30..b598372ffb 100644
--- a/node/defaults.go
+++ b/node/defaults.go
@@ -42,6 +42,7 @@ const (
// needs of all CLs.
engineAPIBatchItemLimit = 2000
engineAPIBatchResponseSizeLimit = 250 * 1000 * 1000
+ engineAPIBodyLimit = 128 * 1024 * 1024
)
var (
diff --git a/node/node.go b/node/node.go
index d63fe85d03..3b7c207af4 100644
--- a/node/node.go
+++ b/node/node.go
@@ -108,7 +108,7 @@ func New(conf *Config) (*Node, error) {
if strings.HasSuffix(conf.Name, ".ipc") {
return nil, errors.New(`Config.Name cannot end in ".ipc"`)
}
- server := rpc.NewServer("inproc", 0, 0)
+ server := rpc.NewServer()
server.SetBatchLimits(conf.BatchRequestLimit, conf.BatchResponseMaxSize)
node := &Node{
config: conf,
@@ -494,14 +494,16 @@ func (n *Node) startRPC() error {
jwtSecret: secret,
batchItemLimit: engineAPIBatchItemLimit,
batchResponseSizeLimit: engineAPIBatchResponseSizeLimit,
+ httpBodyLimit: engineAPIBodyLimit,
}
- if err := server.enableRPC(allAPIs, httpConfig{
+ err := server.enableRPC(allAPIs, httpConfig{
CorsAllowedOrigins: DefaultAuthCors,
Vhosts: n.config.AuthVirtualHosts,
Modules: DefaultAuthModules,
prefix: DefaultAuthPrefix,
rpcEndpointConfig: sharedConfig,
- }); err != nil {
+ })
+ if err != nil {
return err
}
diff --git a/node/rpcstack.go b/node/rpcstack.go
index b8e6df4774..3dfe635fb5 100644
--- a/node/rpcstack.go
+++ b/node/rpcstack.go
@@ -64,6 +64,7 @@ type rpcEndpointConfig struct {
jwtSecret []byte // optional JWT secret
batchItemLimit int
batchResponseSizeLimit int
+ httpBodyLimit int
}
type rpcHandler struct {
@@ -329,10 +330,13 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error {
}
// Create RPC server and handler.
- srv := rpc.NewServer("http", config.executionPoolSize, config.executionPoolRequestTimeout)
+ srv := rpc.NewServer()
srv.SetRPCBatchLimit(h.RPCBatchLimit)
srv.SetBatchLimits(config.batchItemLimit, config.batchResponseSizeLimit)
+ if config.httpBodyLimit > 0 {
+ srv.SetHTTPBodyLimit(config.httpBodyLimit)
+ }
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
@@ -366,10 +370,13 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error {
return fmt.Errorf("JSON-RPC over WebSocket is already enabled")
}
// Create RPC server and handler.
- srv := rpc.NewServer("ws", config.executionPoolSize, config.executionPoolRequestTimeout)
+ srv := rpc.NewServer()
srv.SetRPCBatchLimit(h.RPCBatchLimit)
srv.SetBatchLimits(config.batchItemLimit, config.batchResponseSizeLimit)
+ if config.httpBodyLimit > 0 {
+ srv.SetHTTPBodyLimit(config.httpBodyLimit)
+ }
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
diff --git a/p2p/dnsdisc/tree.go b/p2p/dnsdisc/tree.go
index 4d6686eda2..a5d69b7161 100644
--- a/p2p/dnsdisc/tree.go
+++ b/p2p/dnsdisc/tree.go
@@ -382,13 +382,11 @@ func parseLink(e string) (*linkEntry, error) {
e = e[len(linkPrefix):]
- pos := strings.IndexByte(e, '@')
- if pos == -1 {
+ keystring, domain, found := strings.Cut(e, "@")
+ if !found {
return nil, entryError{"link", errNoPubkey}
}
- keystring, domain := e[:pos], e[pos+1:]
-
keybytes, err := b32format.DecodeString(keystring)
if err != nil {
return nil, entryError{"link", errBadPubkey}
diff --git a/p2p/server.go b/p2p/server.go
index d657b059c8..f1f70fc483 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -1017,14 +1017,14 @@ func (srv *Server) checkInboundConn(remoteIP net.IP) error {
}
// Reject connections that do not match NetRestrict.
if srv.NetRestrict != nil && !srv.NetRestrict.Contains(remoteIP) {
- return fmt.Errorf("not in netrestrict list")
+ return errors.New("not in netrestrict list")
}
// Reject Internet peers that try too often.
now := srv.clock.Now()
srv.inboundHistory.expire(now, nil)
if !netutil.IsLAN(remoteIP) && srv.inboundHistory.contains(remoteIP.String()) {
- return fmt.Errorf("too many attempts")
+ return errors.New("too many attempts")
}
srv.inboundHistory.add(remoteIP.String(), now.Add(inboundThrottleTime))
diff --git a/p2p/server_nat.go b/p2p/server_nat.go
index 354597cc7a..299d275490 100644
--- a/p2p/server_nat.go
+++ b/p2p/server_nat.go
@@ -127,7 +127,7 @@ func (srv *Server) portMappingLoop() {
} else if !ip.Equal(lastExtIP) {
log.Debug("External IP changed", "ip", extip, "interface", srv.NAT)
} else {
- return
+ continue
}
// Here, we either failed to get the external IP, or it has changed.
lastExtIP = ip
diff --git a/p2p/transport.go b/p2p/transport.go
index b4be03a661..ab20ffbf59 100644
--- a/p2p/transport.go
+++ b/p2p/transport.go
@@ -19,6 +19,7 @@ package p2p
import (
"bytes"
"crypto/ecdsa"
+ "errors"
"fmt"
"io"
"net"
@@ -167,7 +168,7 @@ func readProtocolHandshake(rw MsgReader) (*protoHandshake, error) {
}
if msg.Size > baseProtocolMaxMsgSize {
- return nil, fmt.Errorf("message too big")
+ return nil, errors.New("message too big")
}
if msg.Code == discMsg {
diff --git a/params/config.go b/params/config.go
index 963a00b120..f9c1b7ded5 100644
--- a/params/config.go
+++ b/params/config.go
@@ -23,11 +23,13 @@ import (
"strconv"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params/forks"
)
// Genesis hashes to enforce below configs on.
var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
+ HoleskyGenesisHash = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4")
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
@@ -62,6 +64,29 @@ var (
TerminalTotalDifficultyPassed: true,
Ethash: new(EthashConfig),
}
+ // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
+ HoleskyChainConfig = &ChainConfig{
+ ChainID: big.NewInt(17000),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: nil,
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: nil,
+ GrayGlacierBlock: nil,
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ MergeNetsplitBlock: nil,
+ Ethash: new(EthashConfig),
+ }
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
SepoliaChainConfig = &ChainConfig{
ChainID: big.NewInt(11155111),
@@ -490,6 +515,32 @@ var (
BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}},
}
+ // MergedTestChainConfig contains every protocol change (EIPs) introduced
+ // and accepted by the Ethereum core developers for testing purposes.
+ MergedTestChainConfig = &ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ GrayGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ Ethash: new(EthashConfig),
+ Clique: nil,
+ }
+
// NonActivatedConfig defines the chain configuration without activating
// any protocol change (EIPs).
NonActivatedConfig = &ChainConfig{
@@ -978,7 +1029,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork.name, cur.name, cur.block)
} else {
return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at timestamp %v",
- lastFork.name, cur.name, cur.timestamp)
+ lastFork.name, cur.name, *cur.timestamp)
}
// Fork (whether defined by block or timestamp) must follow the fork definition sequence
@@ -988,7 +1039,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork.name, lastFork.block, cur.name, cur.block)
} else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp {
return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v",
- lastFork.name, lastFork.timestamp, cur.name, cur.timestamp)
+ lastFork.name, *lastFork.timestamp, cur.name, *cur.timestamp)
}
// Timestamp based forks can follow block based ones, but not the other way around
@@ -1107,6 +1158,23 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier
}
+// LatestFork returns the latest time-based fork that would be active for the given time.
+func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
+ // Assume last non-time-based fork has passed.
+ london := c.LondonBlock
+
+ switch {
+ case c.IsPrague(london):
+ return forks.Prague
+ case c.IsCancun(london):
+ return forks.Cancun
+ case c.IsShanghai(london):
+ return forks.Shanghai
+ default:
+ return forks.Paris
+ }
+}
+
// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {
@@ -1207,7 +1275,8 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
if chainID == nil {
chainID = new(big.Int)
}
-
+ // disallow setting Merge out of order
+ isMerge = isMerge && c.IsLondon(num)
return Rules{
ChainID: new(big.Int).Set(chainID),
IsHomestead: c.IsHomestead(num),
@@ -1224,5 +1293,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsShanghai: c.IsShanghai(num),
IsCancun: c.IsCancun(num),
IsPrague: c.IsPrague(num),
+ IsVerkle: c.IsVerkle(num),
}
}
diff --git a/params/forks/forks.go b/params/forks/forks.go
new file mode 100644
index 0000000000..4f50ff5aed
--- /dev/null
+++ b/params/forks/forks.go
@@ -0,0 +1,42 @@
+// Copyright 2023 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 forks
+
+// Fork is a numerical identifier of specific network upgrades (forks).
+type Fork int
+
+const (
+ Frontier = iota
+ FrontierThawing
+ Homestead
+ DAO
+ TangerineWhistle
+ SpuriousDragon
+ Byzantium
+ Constantinople
+ Petersburg
+ Istanbul
+ MuirGlacier
+ Berlin
+ London
+ ArrowGlacier
+ GrayGlacier
+ Paris
+ Shanghai
+ Cancun
+ Prague
+)
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 031e3af0be..cb2ee6db76 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -173,7 +173,6 @@ const (
BlobTxBytesPerFieldElement = 32 // Size in bytes of a field element
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
- BlobTxHashVersion = 0x01 // Version byte of the commitment hash
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for blob gas price
diff --git a/rpc/client_test.go b/rpc/client_test.go
index 501a8cd3d3..d37056f7d1 100644
--- a/rpc/client_test.go
+++ b/rpc/client_test.go
@@ -591,7 +591,7 @@ func TestClientSubscriptionUnsubscribeServer(t *testing.T) {
t.Parallel()
// Create the server.
- srv := NewServer("test", 0, 0)
+ srv := NewServer()
srv.RegisterName("nftest", new(notificationTestService))
p1, p2 := net.Pipe()
@@ -634,7 +634,7 @@ func TestClientSubscriptionChannelClose(t *testing.T) {
t.Parallel()
var (
- srv = NewServer("test", 0, 0)
+ srv = NewServer()
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
)
diff --git a/rpc/endpoints.go b/rpc/endpoints.go
index e5f9ab5fa2..040f5db674 100644
--- a/rpc/endpoints.go
+++ b/rpc/endpoints.go
@@ -27,7 +27,7 @@ import (
func StartIPCEndpoint(ipcEndpoint string, apis []API) (net.Listener, *Server, error) {
// Register all the APIs exposed by the services.
var (
- handler = NewServer("", 0, 0) // we can skip reporting ipc metrics, hence empty service name
+ handler = NewServer() // we can skip reporting ipc metrics, hence empty service name
regMap = make(map[string]struct{})
registered []string
)
diff --git a/rpc/http.go b/rpc/http.go
index e8c271bbc9..028df7d5dc 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -33,8 +33,8 @@ import (
)
const (
- maxRequestContentLength = 1024 * 1024 * 5
- contentType = "application/json"
+ defaultBodyLimit = 5 * 1024 * 1024
+ contentType = "application/json"
)
// https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13
@@ -256,8 +256,8 @@ type httpServerConn struct {
r *http.Request
}
-func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
- body := io.LimitReader(r.Body, maxRequestContentLength)
+func (s *Server) newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
+ body := io.LimitReader(r.Body, int64(s.httpBodyLimit))
conn := &httpServerConn{Reader: body, Writer: w, r: r}
encoder := func(v any, isErrorResponse bool) error {
@@ -318,8 +318,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
return
}
-
- if code, err := validateRequest(r); err != nil {
+ if code, err := s.validateRequest(r); err != nil {
http.Error(w, err.Error(), code)
return
}
@@ -337,21 +336,19 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// until EOF, writes the response to w, and orders the server to process a
// single request.
w.Header().Set("content-type", contentType)
-
- codec := newHTTPServerConn(r, w)
+ codec := s.newHTTPServerConn(r, w)
defer codec.close()
s.serveSingleRequest(ctx, codec)
}
// validateRequest returns a non-zero response code and error message if the
// request is invalid.
-func validateRequest(r *http.Request) (int, error) {
+func (s *Server) validateRequest(r *http.Request) (int, error) {
if r.Method == http.MethodPut || r.Method == http.MethodDelete {
return http.StatusMethodNotAllowed, errors.New("method not allowed")
}
-
- if r.ContentLength > maxRequestContentLength {
- err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, maxRequestContentLength)
+ if r.ContentLength > int64(s.httpBodyLimit) {
+ err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, s.httpBodyLimit)
return http.StatusRequestEntityTooLarge, err
}
// Allow OPTIONS (regardless of content-type)
diff --git a/rpc/http_test.go b/rpc/http_test.go
index 5db5f48253..27f5bebe78 100644
--- a/rpc/http_test.go
+++ b/rpc/http_test.go
@@ -44,12 +44,12 @@ func confirmStatusCode(t *testing.T, got, want int) {
func confirmRequestValidationCode(t *testing.T, method, contentType, body string, expectedStatusCode int) {
t.Helper()
+ s := NewServer()
request := httptest.NewRequest(method, "http://url.com", strings.NewReader(body))
if len(contentType) > 0 {
request.Header.Set("Content-Type", contentType)
}
-
- code, err := validateRequest(request)
+ code, err := s.validateRequest(request)
if code == 0 {
if err != nil {
t.Errorf("validation: got error %v, expected nil", err)
@@ -70,7 +70,7 @@ func TestHTTPErrorResponseWithPut(t *testing.T) {
}
func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) {
- body := make([]rune, maxRequestContentLength+1)
+ body := make([]rune, defaultBodyLimit+1)
confirmRequestValidationCode(t,
http.MethodPost, contentType, string(body), http.StatusRequestEntityTooLarge)
}
@@ -115,9 +115,9 @@ func TestHTTPResponseWithEmptyGet(t *testing.T) {
// This checks that maxRequestContentLength is not applied to the response of a request.
func TestHTTPRespBodyUnlimited(t *testing.T) {
- const respLength = maxRequestContentLength * 3
+ const respLength = defaultBodyLimit * 3
- s := NewServer("test", 0, 0)
+ s := NewServer()
defer s.Stop()
s.RegisterName("test", largeRespService{respLength})
diff --git a/rpc/server.go b/rpc/server.go
index 9c953d59df..98e6290ec3 100644
--- a/rpc/server.go
+++ b/rpc/server.go
@@ -57,19 +57,15 @@ type Server struct {
batchItemLimit int
batchResponseLimit int
+ httpBodyLimit int
}
// NewServer creates a new server instance with no registered handlers.
-func NewServer(service string, executionPoolSize uint64, executionPoolRequesttimeout time.Duration) *Server {
- reportEpStats := true
- if service == "" || service == "test" {
- reportEpStats = false
- }
-
+func NewServer() *Server {
server := &Server{
idgen: randomIDGenerator(),
codecs: make(map[ServerCodec]struct{}),
- executionPool: NewExecutionPool(int(executionPoolSize), executionPoolRequesttimeout, service, reportEpStats),
+ httpBodyLimit: defaultBodyLimit,
}
server.run.Store(true)
@@ -112,6 +108,13 @@ func (s *Server) SetBatchLimits(itemLimit, maxResponseSize int) {
s.batchResponseLimit = maxResponseSize
}
+// SetHTTPBodyLimit sets the size limit for HTTP requests.
+//
+// This method should be called before processing any requests via ServeHTTP.
+func (s *Server) SetHTTPBodyLimit(limit int) {
+ s.httpBodyLimit = limit
+}
+
// RegisterName creates a service for the given receiver type under the given name. When no
// methods on the given receiver match the criteria to be either a RPC method or a
// subscription an error is returned. Otherwise a new service is created and added to the
diff --git a/rpc/server_test.go b/rpc/server_test.go
index 7655eadedd..43ee1026ca 100644
--- a/rpc/server_test.go
+++ b/rpc/server_test.go
@@ -29,7 +29,7 @@ import (
)
func TestServerRegisterName(t *testing.T) {
- server := NewServer("test", 0, 0)
+ server := NewServer()
service := new(testService)
svcName := "test"
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index 590cb91696..7df9b681a8 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -61,7 +61,7 @@ func TestSubscriptions(t *testing.T) {
subCount = len(namespaces)
notificationCount = 3
- server = NewServer("test", 0, 0)
+ server = NewServer()
clientConn, serverConn = net.Pipe()
out = json.NewEncoder(clientConn)
in = json.NewDecoder(clientConn)
diff --git a/rpc/testservice_test.go b/rpc/testservice_test.go
index 30e3c1d027..541f49c0f3 100644
--- a/rpc/testservice_test.go
+++ b/rpc/testservice_test.go
@@ -26,7 +26,7 @@ import (
)
func newTestServer() *Server {
- server := NewServer("test", 0, 0)
+ server := NewServer()
server.idgen = sequentialIDGenerator()
if err := server.RegisterName("test", new(testService)); err != nil {
diff --git a/rpc/types.go b/rpc/types.go
index d8ce7a4845..9003d08568 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -19,6 +19,7 @@ package rpc
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"math"
"strconv"
@@ -112,7 +113,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
}
if blckNum > math.MaxInt64 {
- return fmt.Errorf("block number larger than int64")
+ return errors.New("block number larger than int64")
}
*bn = BlockNumber(blckNum)
@@ -166,7 +167,7 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
if err == nil {
if e.BlockNumber != nil && e.BlockHash != nil {
- return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other")
+ return errors.New("cannot specify both BlockHash and BlockNumber, choose one or the other")
}
bnh.BlockNumber = e.BlockNumber
@@ -232,7 +233,7 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
}
if blckNum > math.MaxInt64 {
- return fmt.Errorf("blocknumber too high")
+ return errors.New("blocknumber too high")
}
bn := BlockNumber(blckNum)
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index 019e2f6d02..32b9f85ca4 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -104,8 +104,7 @@ func TestWebsocketLargeCall(t *testing.T) {
// This call sends slightly less than the limit and should work.
var result echoResult
-
- arg := strings.Repeat("x", maxRequestContentLength-200)
+ arg := strings.Repeat("x", defaultBodyLimit-200)
if err := client.Call(&result, "test_echo", arg, 1); err != nil {
t.Fatalf("valid call didn't work: %v", err)
}
@@ -115,7 +114,7 @@ func TestWebsocketLargeCall(t *testing.T) {
}
// This call sends twice the allowed size and shouldn't work.
- arg = strings.Repeat("x", maxRequestContentLength*2)
+ arg = strings.Repeat("x", defaultBodyLimit*2)
err = client.Call(&result, "test_echo", arg)
if err == nil {
@@ -277,7 +276,7 @@ func TestClientWebsocketPing(t *testing.T) {
// This checks that the websocket transport can deal with large messages.
func TestClientWebsocketLargeMessage(t *testing.T) {
var (
- srv = NewServer("test", 0, 0)
+ srv = NewServer()
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
)
diff --git a/signer/core/api.go b/signer/core/api.go
index 0691e98a58..2dfe57f7fb 100644
--- a/signer/core/api.go
+++ b/signer/core/api.go
@@ -65,7 +65,7 @@ type ExternalAPI interface {
EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error)
// Version info about the APIs
Version(ctx context.Context) (string, error)
- // SignGnosisSafeTransaction signs/confirms a gnosis-safe multisig transaction
+ // SignGnosisSafeTx signs/confirms a gnosis-safe multisig transaction
SignGnosisSafeTx(ctx context.Context, signerAddress common.MixedcaseAddress, gnosisTx GnosisSafeTx, methodSelector *string) (*GnosisSafeTx, error)
}
diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go
index aea29918dd..4273c59d72 100644
--- a/signer/core/apitypes/types.go
+++ b/signer/core/apitypes/types.go
@@ -62,7 +62,7 @@ func (vs *ValidationMessages) Info(msg string) {
vs.Messages = append(vs.Messages, ValidationInfo{INFO, msg})
}
-// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
+// GetWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
func (v *ValidationMessages) GetWarnings() error {
var messages []string
diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go
index 6b4d15ea9e..a3075f4e23 100644
--- a/signer/core/signed_data.go
+++ b/signer/core/signed_data.go
@@ -328,7 +328,7 @@ func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hex
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be 27 or 28 for legacy reasons.
//
- // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
+ // https://geth.ethereum.org/docs/tools/clef/apis#account-ecrecover
if len(sig) != 65 {
return common.Address{}, errors.New("signature must be 65 bytes long")
}
diff --git a/signer/core/uiapi.go b/signer/core/uiapi.go
index 0a316c3a97..ca10c487d8 100644
--- a/signer/core/uiapi.go
+++ b/signer/core/uiapi.go
@@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
-// SignerUIAPI implements methods Clef provides for a UI to query, in the bidirectional communication
+// UIServerAPI implements methods Clef provides for a UI to query, in the bidirectional communication
// channel.
// This API is considered secure, since a request can only
// ever arrive from the UI -- and the UI is capable of approving any action, thus we can consider these
diff --git a/tests/block_test.go b/tests/block_test.go
index dd2ba4dbd3..21ab66e76f 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -69,14 +69,14 @@ func TestBlockchain(t *testing.T) {
// which run natively, so there's no reason to run them here.
}
-// TestExecutionSpec runs the test fixtures from execution-spec-tests.
-func TestExecutionSpec(t *testing.T) {
- if !common.FileExist(executionSpecDir) {
- t.Skipf("directory %s does not exist", executionSpecDir)
+// TestExecutionSpecBlocktests runs the test fixtures from execution-spec-tests.
+func TestExecutionSpecBlocktests(t *testing.T) {
+ if !common.FileExist(executionSpecBlockchainTestDir) {
+ t.Skipf("directory %s does not exist", executionSpecBlockchainTestDir)
}
bt := new(testMatcher)
- bt.walk(t, executionSpecDir, func(t *testing.T, name string, test *BlockTest) {
+ bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
execBlockTest(t, bt, test)
})
}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 0bf2e00d9a..cf2639af12 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -36,11 +36,12 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// A BlockTest checks handling of entire blocks.
@@ -56,8 +57,8 @@ func (t *BlockTest) UnmarshalJSON(in []byte) error {
type btJSON struct {
Blocks []btBlock `json:"blocks"`
Genesis btHeader `json:"genesisBlockHeader"`
- Pre core.GenesisAlloc `json:"pre"`
- Post core.GenesisAlloc `json:"postState"`
+ Pre types.GenesisAlloc `json:"pre"`
+ Post types.GenesisAlloc `json:"postState"`
BestBlock common.UnprefixedHash `json:"lastblockhash"`
Network string `json:"network"`
SealEngine string `json:"sealEngine"`
@@ -116,7 +117,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
- tconf = &trie.Config{
+ tconf = &triedb.Config{
Preimages: true,
}
)
@@ -127,7 +128,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
}
// Commit genesis state
gspec := t.genesis(config)
- triedb := trie.NewDatabase(db, tconf)
+ triedb := triedb.NewDatabase(db, tconf)
gblock, err := gspec.Commit(db, triedb)
if err != nil {
return err
@@ -228,6 +229,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
cb, err := b.decode()
if err != nil {
if b.BlockHeader == nil {
+ log.Info("Block decoding failed", "index", bi, "err", err)
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
@@ -351,7 +353,7 @@ func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
for addr, acct := range t.json.Post {
// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
- balance2 := statedb.GetBalance(addr)
+ balance2 := statedb.GetBalance(addr).ToBig()
nonce2 := statedb.GetNonce(addr)
if !bytes.Equal(code2, acct.Code) {
diff --git a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
index ef69a4bac9..3638cbca0b 100644
--- a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
+++ b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"golang.org/x/exp/slices"
)
@@ -58,7 +59,7 @@ func (f *fuzzer) readInt() uint64 {
}
func (f *fuzzer) randomTrie(n int) (*trie.Trie, map[string]*kv) {
- trie := trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))
vals := make(map[string]*kv)
size := f.readInt()
// Fill it with some fluff
diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go
index 5d4208bf25..5fd3f7fbf4 100644
--- a/tests/gen_stenv.go
+++ b/tests/gen_stenv.go
@@ -16,13 +16,14 @@ var _ = (*stEnvMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
- Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var enc stEnv
@@ -33,20 +34,21 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.Number = math.HexOrDecimal64(s.Number)
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee)
-
+ enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
- Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var dec stEnv
@@ -87,6 +89,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.BaseFee != nil {
s.BaseFee = (*big.Int)(dec.BaseFee)
}
-
+ if dec.ExcessBlobGas != nil {
+ s.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
+ }
return nil
}
diff --git a/tests/init_test.go b/tests/init_test.go
index 6cc0427b1d..295e1d722f 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -37,15 +37,16 @@ import (
)
var (
- baseDir = filepath.Join(".", "testdata")
- blockTestDir = filepath.Join(baseDir, "BlockchainTests")
- stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
- legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
- transactionTestDir = filepath.Join(baseDir, "TransactionTests")
- rlpTestDir = filepath.Join(baseDir, "RLPTests")
- difficultyTestDir = filepath.Join(baseDir, "BasicTests")
- executionSpecDir = filepath.Join(".", "spec-tests", "fixtures")
- benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
+ baseDir = filepath.Join(".", "testdata")
+ blockTestDir = filepath.Join(baseDir, "BlockchainTests")
+ stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
+ legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
+ transactionTestDir = filepath.Join(baseDir, "TransactionTests")
+ rlpTestDir = filepath.Join(baseDir, "RLPTests")
+ difficultyTestDir = filepath.Join(baseDir, "BasicTests")
+ executionSpecBlockchainTestDir = filepath.Join(".", "spec-tests", "fixtures", "blockchain_tests")
+ executionSpecStateTestDir = filepath.Join(".", "spec-tests", "fixtures", "state_tests")
+ benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
)
func readJSON(reader io.Reader, value interface{}) error {
diff --git a/tests/state_test.go b/tests/state_test.go
index 575f322007..89f84252bd 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -33,19 +33,16 @@ import (
"testing"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
+ "github.com/holiman/uint256"
)
-func TestState(t *testing.T) {
- t.Parallel()
-
- st := new(testMatcher)
+func initMatcher(st *testMatcher) {
// Long tests:
st.slow(`^stAttackTest/ContractCreationSpam`)
st.slow(`^stBadOpcode/badOpcodes`)
@@ -121,80 +118,102 @@ func TestState(t *testing.T) {
// Broken tests:
// EOF is not part of cancun
st.skipLoad(`^stEOF/`)
+}
- // EIP-4844 tests need to be regenerated due to the data-to-blob rename
- st.skipLoad(`^stEIP4844-blobtransactions/`)
+func TestState(t *testing.T) {
+ t.Parallel()
- // Expected failures:
- // These EIP-4844 tests need to be regenerated.
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`, "test has incorrect state root")
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`, "test has incorrect state root")
-
- // For Istanbul, older tests were moved into LegacyTests
+ st := new(testMatcher)
+ initMatcher(st)
for _, dir := range []string{
filepath.Join(baseDir, "EIPTests", "StateTests"),
stateTestDir,
- legacyStateTestDir,
benchmarksDir,
} {
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
- if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
- t.Skip("test (randomly) skipped on 32-bit windows")
- return
- }
- for _, subtest := range test.Subtests() {
- subtest := subtest
- key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
+ execStateTest(t, st, test)
+ })
+ }
+}
- t.Run(key+"/hash/trie", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- result = st.checkFailure(t, err)
- })
- return result
- })
+// TestLegacyState tests some older tests, which were moved to the folder
+// 'LegacyTests' for the Istanbul fork.
+func TestLegacyState(t *testing.T) {
+ st := new(testMatcher)
+ initMatcher(st)
+ st.walk(t, legacyStateTestDir, func(t *testing.T, name string, test *StateTest) {
+ execStateTest(t, st, test)
+ })
+}
+
+// TestExecutionSpecState runs the test fixtures from execution-spec-tests.
+func TestExecutionSpecState(t *testing.T) {
+ if !common.FileExist(executionSpecStateTestDir) {
+ t.Skipf("directory %s does not exist", executionSpecStateTestDir)
+ }
+ st := new(testMatcher)
+
+ st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) {
+ execStateTest(t, st, test)
+ })
+}
+
+func execStateTest(t *testing.T, st *testMatcher, test *StateTest) {
+ if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
+ t.Skip("test (randomly) skipped on 32-bit windows")
+ return
+ }
+ for _, subtest := range test.Subtests() {
+ subtest := subtest
+ key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
+
+ t.Run(key+"/hash/trie", func(t *testing.T) {
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, state *StateTestState) {
+ result = st.checkFailure(t, err)
})
- t.Run(key+"/hash/snap", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- if snaps != nil && state != nil {
- if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
- result = err
- return
- }
- }
- result = st.checkFailure(t, err)
- })
- return result
- })
+ return result
+ })
+ })
+ t.Run(key+"/hash/snap", func(t *testing.T) {
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, state *StateTestState) {
+ if state.Snapshots != nil && state.StateDB != nil {
+ if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
+ result = err
+ return
+ }
+ }
+ result = st.checkFailure(t, err)
})
- t.Run(key+"/path/trie", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- result = st.checkFailure(t, err)
- })
- return result
- })
+ return result
+ })
+ })
+ t.Run(key+"/path/trie", func(t *testing.T) {
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, state *StateTestState) {
+ result = st.checkFailure(t, err)
})
- t.Run(key+"/path/snap", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- if snaps != nil && state != nil {
- if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
- result = err
- return
- }
- }
- result = st.checkFailure(t, err)
- })
- return result
- })
+ return result
+ })
+ })
+ t.Run(key+"/path/snap", func(t *testing.T) {
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, state *StateTestState) {
+ if state.Snapshots != nil && state.StateDB != nil {
+ if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
+ result = err
+ return
+ }
+ }
+ result = st.checkFailure(t, err)
})
- }
+ return result
+ })
})
}
}
@@ -289,8 +308,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
- triedb, _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
- defer triedb.Close()
+ state := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
+ defer state.Close()
var baseFee *big.Int
if rules.IsLondon {
@@ -328,7 +347,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
- evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
+ evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
// Create "contract" for sender to cache code analysis.
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),
@@ -341,13 +360,13 @@ func runBenchmark(b *testing.B, t *StateTest) {
)
b.ResetTimer()
for n := 0; n < b.N; n++ {
- snapshot := statedb.Snapshot()
- statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
+ snapshot := state.StateDB.Snapshot()
+ state.StateDB.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
b.StartTimer()
start := time.Now()
// Execute the message.
- _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, msg.Value, nil)
+ _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value), nil)
if err != nil {
b.Error(err)
return
@@ -355,10 +374,10 @@ func runBenchmark(b *testing.B, t *StateTest) {
b.StopTimer()
elapsed += uint64(time.Since(start))
- refund += statedb.GetRefund()
+ refund += state.StateDB.GetRefund()
gasUsed += msg.GasLimit - leftOverGas
- statedb.RevertToSnapshot(snapshot)
+ state.StateDB.RevertToSnapshot(snapshot)
}
if elapsed < 1 {
elapsed = 1
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index fbb35a2fbb..3926e90af4 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -25,11 +25,10 @@ import (
"strconv"
"strings"
- "golang.org/x/crypto/sha3"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
@@ -40,9 +39,11 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
+ "golang.org/x/crypto/sha3"
)
// StateTest checks transaction processing without block context.
@@ -63,7 +64,7 @@ func (t *StateTest) UnmarshalJSON(in []byte) error {
type stJSON struct {
Env stEnv `json:"env"`
- Pre core.GenesisAlloc `json:"pre"`
+ Pre types.GenesisAlloc `json:"pre"`
Tx stTransaction `json:"transaction"`
Out hexutil.Bytes `json:"out"`
Post map[string][]stPostState `json:"post"`
@@ -84,23 +85,25 @@ type stPostState struct {
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
- Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
- Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
- Random *big.Int `json:"currentRandom" gencodec:"optional"`
- GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
- Number uint64 `json:"currentNumber" gencodec:"required"`
- Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
+ Random *big.Int `json:"currentRandom" gencodec:"optional"`
+ GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
+ Number uint64 `json:"currentNumber" gencodec:"required"`
+ Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *uint64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
type stEnvMarshaling struct {
- Coinbase common.UnprefixedAddress
- Difficulty *math.HexOrDecimal256
- Random *math.HexOrDecimal256
- GasLimit math.HexOrDecimal64
- Number math.HexOrDecimal64
- Timestamp math.HexOrDecimal64
- BaseFee *math.HexOrDecimal256
+ Coinbase common.UnprefixedAddress
+ Difficulty *math.HexOrDecimal256
+ Random *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ Number math.HexOrDecimal64
+ Timestamp math.HexOrDecimal64
+ BaseFee *math.HexOrDecimal256
+ ExcessBlobGas *math.HexOrDecimal64
}
//go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
@@ -201,20 +204,14 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error {
}
// Run executes a specific subtest and verifies the post-state and logs
-func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) {
- triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
-
+func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) {
+ st, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
// Invoke the callback at the end of function for further analysis.
defer func() {
- postCheck(result, snaps, statedb)
-
- if triedb != nil {
- triedb.Close()
- }
- if snaps != nil {
- snaps.Release()
- }
+ postCheck(result, &st)
+ st.Close()
}()
+
checkedErr := t.checkError(subtest, err)
if checkedErr != nil {
return checkedErr
@@ -232,25 +229,25 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
if root != common.Hash(post.Root) {
return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
}
-
- if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
+ if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
}
- statedb, _ = state.New(root, statedb.Database(), snaps)
+ st.StateDB, _ = state.New(root, st.StateDB.Database(), st.Snapshots)
return nil
}
-// RunNoVerify runs a specific subtest and returns the statedb and post-state root
-func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) {
+// RunNoVerify runs a specific subtest and returns the statedb and post-state root.
+// Remember to call state.Close after verifying the test result!
+func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (state StateTestState, root common.Hash, err error) {
config, eips, err := GetChainConfig(subtest.Fork)
if err != nil {
- return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
+ return state, common.Hash{}, UnsupportedForkError{subtest.Fork}
}
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
- triedb, snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
+ state = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
var baseFee *big.Int
if config.IsLondon(new(big.Int)) {
@@ -266,8 +263,18 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
msg, err := t.json.Tx.toMessage(post, baseFee)
if err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return state, common.Hash{}, err
+ }
+
+ { // Blob transactions may be present after the Cancun fork.
+ // In production,
+ // - the header is verified against the max in eip4844.go:VerifyEIP4844Header
+ // - the block body is verified against the header in block_validator.go:ValidateBody
+ // Here, we just do this shortcut smaller fix, since state tests do not
+ // utilize those codepaths
+ if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
+ return state, common.Hash{}, errors.New("blob gas exceeds maximum")
+ }
}
// Try to recover tx with current signer
@@ -276,13 +283,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
err := ttx.UnmarshalBinary(post.TxBytes)
if err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return state, common.Hash{}, err
}
-
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return state, common.Hash{}, err
}
}
@@ -302,28 +306,30 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
context.Random = &rnd
context.Difficulty = big.NewInt(0)
}
-
- evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
+ if config.IsCancun(block.Number()) && t.json.Env.ExcessBlobGas != nil {
+ context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
+ }
+ evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
// Execute the message.
- snapshot := statedb.Snapshot()
+ snapshot := state.StateDB.Snapshot()
gaspool := new(core.GasPool)
gaspool.AddGas(block.GasLimit())
_, err = core.ApplyMessage(evm, msg, gaspool, nil)
if err != nil {
- statedb.RevertToSnapshot(snapshot)
+ state.StateDB.RevertToSnapshot(snapshot)
}
// Add 0-value mining reward. This only makes a difference in the cases
// where
// - the coinbase self-destructed, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
- statedb.AddBalance(block.Coinbase(), new(big.Int))
+ state.StateDB.AddBalance(block.Coinbase(), new(uint256.Int))
// Commit state mutations into database.
- root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
- return triedb, snaps, statedb, root, err
+ root, _ = state.StateDB.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
+ return state, root, err
}
// nolint:unused
@@ -331,44 +337,6 @@ func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
}
-func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB) {
- tconf := &trie.Config{Preimages: true}
- if scheme == rawdb.HashScheme {
- tconf.HashDB = hashdb.Defaults
- } else {
- tconf.PathDB = pathdb.Defaults
- }
- triedb := trie.NewDatabase(db, tconf)
- sdb := state.NewDatabaseWithNodeDB(db, triedb)
- statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
- for addr, a := range accounts {
- statedb.SetCode(addr, a.Code)
- statedb.SetNonce(addr, a.Nonce)
- statedb.SetBalance(addr, a.Balance)
-
- for k, v := range a.Storage {
- statedb.SetState(addr, k, v)
- }
- }
- // Commit and re-open to start with a clean state.
- root, _ := statedb.Commit(0, false)
-
- var snaps *snapshot.Tree
-
- if snapshotter {
- snapconfig := snapshot.Config{
- CacheSize: 1,
- Recovery: false,
- NoBuild: false,
- AsyncBuild: false,
- }
- snaps, _ = snapshot.New(snapconfig, db, triedb, root)
- }
-
- statedb, _ = state.New(root, sdb, snaps)
- return triedb, snaps, statedb
-}
-
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
genesis := &core.Genesis{
Config: config,
@@ -501,3 +469,61 @@ func rlpHash(x interface{}) (h common.Hash) {
func vmTestBlockHash(n uint64) common.Hash {
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
}
+
+// StateTestState groups all the state database objects together for use in tests.
+type StateTestState struct {
+ StateDB *state.StateDB
+ TrieDB *triedb.Database
+ Snapshots *snapshot.Tree
+}
+
+// MakePreState creates a state containing the given allocation.
+func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bool, scheme string) StateTestState {
+ tconf := &triedb.Config{Preimages: true}
+ if scheme == rawdb.HashScheme {
+ tconf.HashDB = hashdb.Defaults
+ } else {
+ tconf.PathDB = pathdb.Defaults
+ }
+ triedb := triedb.NewDatabase(db, tconf)
+ sdb := state.NewDatabaseWithNodeDB(db, triedb)
+ statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
+ for addr, a := range accounts {
+ statedb.SetCode(addr, a.Code)
+ statedb.SetNonce(addr, a.Nonce)
+ statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
+ for k, v := range a.Storage {
+ statedb.SetState(addr, k, v)
+ }
+ }
+ // Commit and re-open to start with a clean state.
+ root, _ := statedb.Commit(0, false)
+
+ // If snapshot is requested, initialize the snapshotter and use it in state.
+ var snaps *snapshot.Tree
+ if snapshotter {
+ snapconfig := snapshot.Config{
+ CacheSize: 1,
+ Recovery: false,
+ NoBuild: false,
+ AsyncBuild: false,
+ }
+ snaps, _ = snapshot.New(snapconfig, db, triedb, root)
+ }
+ statedb, _ = state.New(root, sdb, snaps)
+ return StateTestState{statedb, triedb, snaps}
+}
+
+// Close should be called when the state is no longer needed, ie. after running the test.
+func (st *StateTestState) Close() {
+ if st.TrieDB != nil {
+ st.TrieDB.Close()
+ st.TrieDB = nil
+ }
+ if st.Snapshots != nil {
+ // Need to call Disable here to quit the snapshot generator goroutine.
+ st.Snapshots.Disable()
+ st.Snapshots.Release()
+ st.Snapshots = nil
+ }
+}
diff --git a/trie/committer.go b/trie/committer.go
index 0c5dfb922e..6a50791e67 100644
--- a/trie/committer.go
+++ b/trie/committer.go
@@ -161,12 +161,12 @@ func (c *committer) store(path []byte, n node) node {
return hash
}
-// mptResolver the children resolver in merkle-patricia-tree.
-type mptResolver struct{}
+// MerkleResolver the children resolver in merkle-patricia-tree.
+type MerkleResolver struct{}
// ForEach implements childResolver, decodes the provided node and
// traverses the children inside.
-func (resolver mptResolver) ForEach(node []byte, onChild func(common.Hash)) {
+func (resolver MerkleResolver) ForEach(node []byte, onChild func(common.Hash)) {
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
}
diff --git a/trie/database_test.go b/trie/database_test.go
index d508c65533..aed508b368 100644
--- a/trie/database_test.go
+++ b/trie/database_test.go
@@ -17,24 +17,136 @@
package trie
import (
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
-// newTestDatabase initializes the trie database with specified scheme.
-func newTestDatabase(diskdb ethdb.Database, scheme string) *Database {
- config := &Config{Preimages: false}
- if scheme == rawdb.HashScheme {
- config.HashDB = &hashdb.Config{
- CleanCacheSize: 0,
- } // disable clean cache
- } else {
- config.PathDB = &pathdb.Config{
- CleanCacheSize: 0,
- DirtyCacheSize: 0,
- } // disable clean/dirty cache
- }
- return NewDatabase(diskdb, config)
+// testReader implements database.Reader interface, providing function to
+// access trie nodes.
+type testReader struct {
+ db ethdb.Database
+ scheme string
+ nodes []*trienode.MergedNodeSet // sorted from new to old
+}
+
+// Node implements database.Reader interface, retrieving trie node with
+// all available cached layers.
+func (r *testReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
+ // Check the node presence with the cached layer, from latest to oldest.
+ for _, nodes := range r.nodes {
+ if _, ok := nodes.Sets[owner]; !ok {
+ continue
+ }
+ n, ok := nodes.Sets[owner].Nodes[string(path)]
+ if !ok {
+ continue
+ }
+ if n.IsDeleted() || n.Hash != hash {
+ return nil, &MissingNodeError{Owner: owner, Path: path, NodeHash: hash}
+ }
+ return n.Blob, nil
+ }
+ // Check the node presence in database.
+ return rawdb.ReadTrieNode(r.db, owner, path, hash, r.scheme), nil
+}
+
+// testDb implements database.Database interface, using for testing purpose.
+type testDb struct {
+ disk ethdb.Database
+ root common.Hash
+ scheme string
+ nodes map[common.Hash]*trienode.MergedNodeSet
+ parents map[common.Hash]common.Hash
+}
+
+func newTestDatabase(diskdb ethdb.Database, scheme string) *testDb {
+ return &testDb{
+ disk: diskdb,
+ root: types.EmptyRootHash,
+ scheme: scheme,
+ nodes: make(map[common.Hash]*trienode.MergedNodeSet),
+ parents: make(map[common.Hash]common.Hash),
+ }
+}
+
+func (db *testDb) Reader(stateRoot common.Hash) (database.Reader, error) {
+ nodes, _ := db.dirties(stateRoot, true)
+ return &testReader{db: db.disk, scheme: db.scheme, nodes: nodes}, nil
+}
+
+func (db *testDb) Preimage(hash common.Hash) []byte {
+ return rawdb.ReadPreimage(db.disk, hash)
+}
+
+func (db *testDb) InsertPreimage(preimages map[common.Hash][]byte) {
+ rawdb.WritePreimages(db.disk, preimages)
+}
+
+func (db *testDb) Scheme() string { return db.scheme }
+
+func (db *testDb) Update(root common.Hash, parent common.Hash, nodes *trienode.MergedNodeSet) error {
+ if root == parent {
+ return nil
+ }
+ if _, ok := db.nodes[root]; ok {
+ return nil
+ }
+ db.parents[root] = parent
+ db.nodes[root] = nodes
+ return nil
+}
+
+func (db *testDb) dirties(root common.Hash, topToBottom bool) ([]*trienode.MergedNodeSet, []common.Hash) {
+ var (
+ pending []*trienode.MergedNodeSet
+ roots []common.Hash
+ )
+ for {
+ if root == db.root {
+ break
+ }
+ nodes, ok := db.nodes[root]
+ if !ok {
+ break
+ }
+ if topToBottom {
+ pending = append(pending, nodes)
+ roots = append(roots, root)
+ } else {
+ pending = append([]*trienode.MergedNodeSet{nodes}, pending...)
+ roots = append([]common.Hash{root}, roots...)
+ }
+ root = db.parents[root]
+ }
+ return pending, roots
+}
+
+func (db *testDb) Commit(root common.Hash) error {
+ if root == db.root {
+ return nil
+ }
+ pending, roots := db.dirties(root, false)
+ for i, nodes := range pending {
+ for owner, set := range nodes.Sets {
+ if owner == (common.Hash{}) {
+ continue
+ }
+ set.ForEachWithOrder(func(path string, n *trienode.Node) {
+ rawdb.WriteTrieNode(db.disk, owner, []byte(path), n.Hash, n.Blob, db.scheme)
+ })
+ }
+ nodes.Sets[common.Hash{}].ForEachWithOrder(func(path string, n *trienode.Node) {
+ rawdb.WriteTrieNode(db.disk, common.Hash{}, []byte(path), n.Hash, n.Blob, db.scheme)
+ })
+ db.root = roots[i]
+ }
+ for _, root := range roots {
+ delete(db.nodes, root)
+ delete(db.parents, root)
+ }
+ return nil
}
diff --git a/trie/iterator_test.go b/trie/iterator_test.go
index e3ecbd1fdf..ac808d8849 100644
--- a/trie/iterator_test.go
+++ b/trie/iterator_test.go
@@ -30,7 +30,7 @@ import (
)
func TestEmptyIterator(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
iter := trie.MustNodeIterator(nil)
seen := make(map[string]struct{})
@@ -44,7 +44,7 @@ func TestEmptyIterator(t *testing.T) {
}
func TestIterator(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -62,7 +62,7 @@ func TestIterator(t *testing.T) {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
found := make(map[string]string)
@@ -88,7 +88,7 @@ func (k *kv) cmp(other *kv) int {
}
func TestIteratorLargeData(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
for i := byte(0); i < 255; i++ {
@@ -212,7 +212,7 @@ var testdata2 = []kvs{
}
func TestIteratorSeek(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for _, val := range testdata1 {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -257,22 +257,22 @@ func checkIteratorOrder(want []kvs, it *Iterator) error {
}
func TestDifferenceIterator(t *testing.T) {
- dba := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dba := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
triea := NewEmpty(dba)
for _, val := range testdata1 {
triea.MustUpdate([]byte(val.k), []byte(val.v))
}
rootA, nodesA, _ := triea.Commit(false)
- dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
+ dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
triea, _ = New(TrieID(rootA), dba)
- dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trieb := NewEmpty(dbb)
for _, val := range testdata2 {
trieb.MustUpdate([]byte(val.k), []byte(val.v))
}
rootB, nodesB, _ := trieb.Commit(false)
- dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
+ dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
trieb, _ = New(TrieID(rootB), dbb)
found := make(map[string]string)
@@ -300,22 +300,22 @@ func TestDifferenceIterator(t *testing.T) {
}
func TestUnionIterator(t *testing.T) {
- dba := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dba := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
triea := NewEmpty(dba)
for _, val := range testdata1 {
triea.MustUpdate([]byte(val.k), []byte(val.v))
}
rootA, nodesA, _ := triea.Commit(false)
- dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
+ dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
triea, _ = New(TrieID(rootA), dba)
- dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trieb := NewEmpty(dbb)
for _, val := range testdata2 {
trieb.MustUpdate([]byte(val.k), []byte(val.v))
}
rootB, nodesB, _ := trieb.Commit(false)
- dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
+ dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
trieb, _ = New(TrieID(rootB), dbb)
di, _ := NewUnionIterator([]NodeIterator{triea.MustNodeIterator(nil), trieb.MustNodeIterator(nil)})
@@ -356,7 +356,8 @@ func TestUnionIterator(t *testing.T) {
}
func TestIteratorNoDups(t *testing.T) {
- tr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ tr := NewEmpty(db)
for _, val := range testdata1 {
tr.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -380,9 +381,9 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) {
tr.MustUpdate([]byte(val.k), []byte(val.v))
}
root, nodes, _ := tr.Commit(false)
- tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- tdb.Commit(root, false)
+ tdb.Commit(root)
}
tr, _ = New(TrieID(root), tdb)
wantNodeCount := checkIteratorNoDups(t, tr.MustNodeIterator(nil), nil)
@@ -505,9 +506,9 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin
break
}
}
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- _ = triedb.Commit(root, false)
+ _ = triedb.Commit(root)
}
var (
barNodeBlob []byte
@@ -586,8 +587,8 @@ func testIteratorNodeBlob(t *testing.T, scheme string) {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- triedb.Commit(root, false)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ triedb.Commit(root)
var found = make(map[common.Hash][]byte)
trie, _ = New(TrieID(root), triedb)
diff --git a/trie/proof.go b/trie/proof.go
index c43a022248..a148ea208e 100644
--- a/trie/proof.go
+++ b/trie/proof.go
@@ -428,7 +428,7 @@ func unset(parent node, child node, key []byte, pos int, removeLeft bool) error
} else {
if bytes.Compare(cld.Key, key[pos:]) > 0 {
// The key of fork shortnode is greater than the
- // path(it belongs to the range), unset the entire
+ // path(it belongs to the range), unset the entries
// branch. The parent must be a fullnode.
fn := parent.(*fullNode)
fn.Children[key[pos-1]] = nil
diff --git a/trie/proof_test.go b/trie/proof_test.go
index 08557940f9..163b8962c0 100644
--- a/trie/proof_test.go
+++ b/trie/proof_test.go
@@ -102,7 +102,7 @@ func TestProof(t *testing.T) {
}
func TestOneElementProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "k", "v")
for i, prover := range makeProvers(trie) {
@@ -160,7 +160,7 @@ func TestBadProof(t *testing.T) {
// Tests that missing keys can also be proven. The test explicitly uses a single
// entry trie and checks for missing keys both before and after the single entry.
func TestMissingKeyProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "k", "v")
for i, key := range []string{"a", "j", "l", "z"} {
@@ -369,7 +369,7 @@ func TestOneElementRangeProof(t *testing.T) {
}
// Test the mini trie with only a single element.
- tinyTrie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ tinyTrie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
entry := &kv{randBytes(32), randBytes(20), false}
tinyTrie.MustUpdate(entry.k, entry.v)
@@ -443,7 +443,7 @@ func TestAllElementsProof(t *testing.T) {
// TestSingleSideRangeProof tests the range starts from zero.
func TestSingleSideRangeProof(t *testing.T) {
for i := 0; i < 64; i++ {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv
for i := 0; i < 4096; i++ {
value := &kv{randBytes(32), randBytes(20), false}
@@ -560,7 +560,7 @@ func TestBadRangeProof(t *testing.T) {
// TestGappedRangeProof focuses on the small trie with embedded nodes.
// If the gapped node is embedded in the trie, it should be detected too.
func TestGappedRangeProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv // Sorted entries
for i := byte(0); i < 10; i++ {
@@ -638,7 +638,7 @@ func TestSameSideProofs(t *testing.T) {
}
func TestHasRightElement(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv
for i := 0; i < 4096; i++ {
value := &kv{randBytes(32), randBytes(20), false}
@@ -1015,7 +1015,7 @@ func benchmarkVerifyRangeNoProof(b *testing.B, size int) {
}
func randomTrie(n int) (*Trie, map[string]*kv) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
for i := byte(0); i < 100; i++ {
@@ -1039,7 +1039,7 @@ func randomTrie(n int) (*Trie, map[string]*kv) {
}
func nonRandomTrie(n int) (*Trie, map[string]*kv) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
max := uint64(0xffffffffffffffff)
@@ -1066,7 +1066,7 @@ func TestRangeProofKeysWithSharedPrefix(t *testing.T) {
common.Hex2Bytes("02"),
common.Hex2Bytes("03"),
}
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i, key := range keys {
trie.MustUpdate(key, vals[i])
}
diff --git a/trie/secure_trie.go b/trie/secure_trie.go
index 99cdfac576..efd4dfb5d3 100644
--- a/trie/secure_trie.go
+++ b/trie/secure_trie.go
@@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
// SecureTrie is the old name of StateTrie.
@@ -29,7 +30,7 @@ type SecureTrie = StateTrie
// NewSecure creates a new StateTrie.
// Deprecated: use NewStateTrie.
-func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db *Database) (*SecureTrie, error) {
+func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db database.Database) (*SecureTrie, error) {
id := &ID{
StateRoot: stateRoot,
Owner: owner,
@@ -50,7 +51,7 @@ func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db *D
// StateTrie is not safe for concurrent use.
type StateTrie struct {
trie Trie
- preimages *preimageStore
+ db database.Database
hashKeyBuf [common.HashLength]byte
secKeyCache map[string][]byte
secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch
@@ -61,7 +62,7 @@ type StateTrie struct {
// If root is the zero hash or the sha3 hash of an empty string, the
// trie is initially empty. Otherwise, New will panic if db is nil
// and returns MissingNodeError if the root node cannot be found.
-func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
+func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
if db == nil {
panic("trie.NewStateTrie called without a database")
}
@@ -69,8 +70,7 @@ func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
if err != nil {
return nil, err
}
- // nolint
- return &StateTrie{trie: *trie, preimages: db.preimages}, nil
+ return &StateTrie{trie: *trie, db: db}, nil
}
// MustGet returns the value for key stored in the trie.
@@ -211,10 +211,7 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
if key, ok := t.getSecKeyCache()[string(shaKey)]; ok {
return key
}
- if t.preimages == nil {
- return nil
- }
- return t.preimages.preimage(common.BytesToHash(shaKey))
+ return t.db.Preimage(common.BytesToHash(shaKey))
}
// Commit collects all dirty nodes in the trie and replaces them with the
@@ -227,13 +224,11 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
// Write all the pre-images to the actual disk database
if len(t.getSecKeyCache()) > 0 {
- if t.preimages != nil {
- preimages := make(map[common.Hash][]byte)
- for hk, key := range t.secKeyCache {
- preimages[common.BytesToHash([]byte(hk))] = key
- }
- t.preimages.insertPreimage(preimages)
+ preimages := make(map[common.Hash][]byte)
+ for hk, key := range t.secKeyCache {
+ preimages[common.BytesToHash([]byte(hk))] = key
}
+ t.db.InsertPreimage(preimages)
t.secKeyCache = make(map[string][]byte)
}
// Commit the trie and return its modified nodeset.
@@ -250,7 +245,7 @@ func (t *StateTrie) Hash() common.Hash {
func (t *StateTrie) Copy() *StateTrie {
return &StateTrie{
trie: *t.trie.Copy(),
- preimages: t.preimages,
+ db: t.db,
secKeyCache: t.secKeyCache,
}
}
diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go
index 0fa003f8ce..e725491943 100644
--- a/trie/secure_trie_test.go
+++ b/trie/secure_trie_test.go
@@ -31,14 +31,14 @@ import (
)
func newEmptySecure() *StateTrie {
- trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
return trie
}
// makeTestStateTrie creates a large enough secure trie for testing.
-func makeTestStateTrie() (*Database, *StateTrie, map[string][]byte) {
+func makeTestStateTrie() (*testDb, *StateTrie, map[string][]byte) {
// Create an empty trie
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb)
// Fill it with some arbitrary data
@@ -62,7 +62,7 @@ func makeTestStateTrie() (*Database, *StateTrie, map[string][]byte) {
}
}
root, nodes, _ := trie.Commit(false)
- if err := triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
panic(fmt.Errorf("failed to commit db %v", err))
}
// Re-create the trie based on the new state
diff --git a/trie/stacktrie.go b/trie/stacktrie.go
index 3724712166..6aea3e1f27 100644
--- a/trie/stacktrie.go
+++ b/trie/stacktrie.go
@@ -23,8 +23,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/metrics"
)
var (
@@ -32,62 +30,32 @@ var (
_ = types.TrieHasher((*StackTrie)(nil))
)
-// StackTrieOptions contains the configured options for manipulating the stackTrie.
-type StackTrieOptions struct {
- Writer func(path []byte, hash common.Hash, blob []byte) // The function to commit the dirty nodes
- Cleaner func(path []byte) // The function to clean up dangling nodes
-
- SkipLeftBoundary bool // Flag whether the nodes on the left boundary are skipped for committing
- SkipRightBoundary bool // Flag whether the nodes on the right boundary are skipped for committing
- boundaryGauge metrics.Gauge // Gauge to track how many boundary nodes are met
-}
-
-// NewStackTrieOptions initializes an empty options for stackTrie.
-func NewStackTrieOptions() *StackTrieOptions { return &StackTrieOptions{} }
-
-// WithWriter configures trie node writer within the options.
-func (o *StackTrieOptions) WithWriter(writer func(path []byte, hash common.Hash, blob []byte)) *StackTrieOptions {
- o.Writer = writer
- return o
-}
-
-// WithCleaner configures the cleaner in the option for removing dangling nodes.
-func (o *StackTrieOptions) WithCleaner(cleaner func(path []byte)) *StackTrieOptions {
- o.Cleaner = cleaner
- return o
-}
-
-// WithSkipBoundary configures whether the left and right boundary nodes are
-// filtered for committing, along with a gauge metrics to track how many
-// boundary nodes are met.
-func (o *StackTrieOptions) WithSkipBoundary(skipLeft, skipRight bool, gauge metrics.Gauge) *StackTrieOptions {
- o.SkipLeftBoundary = skipLeft
- o.SkipRightBoundary = skipRight
- o.boundaryGauge = gauge
- return o
-}
+// OnTrieNode is a callback method invoked when a trie node is committed
+// by the stack trie. The node is only committed if it's considered complete.
+//
+// The caller should not modify the contents of the returned path and blob
+// slice, and their contents may be changed after the call. It is up to the
+// `onTrieNode` receiver function to deep-copy the data if it wants to retain
+// it after the call ends.
+type OnTrieNode func(path []byte, hash common.Hash, blob []byte)
// StackTrie is a trie implementation that expects keys to be inserted
// in order. Once it determines that a subtree will no longer be inserted
// into, it will hash it and free up the memory it uses.
type StackTrie struct {
- options *StackTrieOptions
- root *stNode
- h *hasher
-
- first []byte // The (hex-encoded without terminator) key of first inserted entry, tracked as left boundary.
- last []byte // The (hex-encoded without terminator) key of last inserted entry, tracked as right boundary.
+ root *stNode
+ h *hasher
+ last []byte
+ onTrieNode OnTrieNode
}
-// NewStackTrie allocates and initializes an empty trie.
-func NewStackTrie(options *StackTrieOptions) *StackTrie {
- if options == nil {
- options = NewStackTrieOptions()
- }
+// NewStackTrie allocates and initializes an empty trie. The committed nodes
+// will be discarded immediately if no callback is configured.
+func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
return &StackTrie{
- options: options,
- root: stPool.Get().(*stNode),
- h: newHasher(false),
+ root: stPool.Get().(*stNode),
+ h: newHasher(false),
+ onTrieNode: onTrieNode,
}
}
@@ -101,10 +69,6 @@ func (t *StackTrie) Update(key, value []byte) error {
if bytes.Compare(t.last, k) >= 0 {
return errors.New("non-ascending key order")
}
- // track the first and last inserted entries.
- if t.first == nil {
- t.first = append([]byte{}, k...)
- }
if t.last == nil {
t.last = append([]byte{}, k...) // allocate key slice
} else {
@@ -114,19 +78,9 @@ func (t *StackTrie) Update(key, value []byte) error {
return nil
}
-// MustUpdate is a wrapper of Update and will omit any encountered error but
-// just print out an error message.
-func (t *StackTrie) MustUpdate(key, value []byte) {
- if err := t.Update(key, value); err != nil {
- log.Error("Unhandled trie error in StackTrie.Update", "err", err)
- }
-}
-
// Reset resets the stack trie object to empty state.
func (t *StackTrie) Reset() {
- t.options = NewStackTrieOptions()
t.root = stPool.Get().(*stNode)
- t.first = nil
t.last = nil
}
@@ -349,10 +303,7 @@ func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) {
//
// This method also sets 'st.type' to hashedNode, and clears 'st.key'.
func (t *StackTrie) hash(st *stNode, path []byte) {
- var (
- blob []byte // RLP-encoded node blob
- internal [][]byte // List of node paths covered by the extension node
- )
+ var blob []byte // RLP-encoded node blob
switch st.typ {
case hashedNode:
return
@@ -387,15 +338,6 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
// recursively hash and commit child as the first step
t.hash(st.children[0], append(path, st.key...))
- // Collect the path of internal nodes between shortNode and its **in disk**
- // child. This is essential in the case of path mode scheme to avoid leaving
- // danging nodes within the range of this internal path on disk, which would
- // break the guarantee for state healing.
- if len(st.children[0].val) >= 32 && t.options.Cleaner != nil {
- for i := 1; i < len(st.key); i++ {
- internal = append(internal, append(path, st.key[:i]...))
- }
- }
// encode the extension node
n := shortNode{Key: hexToCompactInPlace(st.key)}
if len(st.children[0].val) < 32 {
@@ -419,11 +361,12 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
default:
panic("invalid node type")
}
-
+ // Convert the node type to hashNode and reset the key slice.
st.typ = hashedNode
st.key = st.key[:0]
- // Skip committing the non-root node if the size is smaller than 32 bytes.
+ // Skip committing the non-root node if the size is smaller than 32 bytes
+ // as tiny nodes are always embedded in their parent except root node.
if len(blob) < 32 && len(path) > 0 {
st.val = common.CopyBytes(blob)
return
@@ -432,51 +375,20 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
// input values.
st.val = t.h.hashData(blob)
- // Short circuit if the stack trie is not configured for writing.
- if t.options.Writer == nil {
- return
+ // Invoke the callback it's provided. Notably, the path and blob slices are
+ // volatile, please deep-copy the slices in callback if the contents need
+ // to be retained.
+ if t.onTrieNode != nil {
+ t.onTrieNode(path, common.BytesToHash(st.val), blob)
}
- // Skip committing if the node is on the left boundary and stackTrie is
- // configured to filter the boundary.
- if t.options.SkipLeftBoundary && bytes.HasPrefix(t.first, path) {
- if t.options.boundaryGauge != nil {
- t.options.boundaryGauge.Inc(1)
- }
- return
- }
- // Skip committing if the node is on the right boundary and stackTrie is
- // configured to filter the boundary.
- if t.options.SkipRightBoundary && bytes.HasPrefix(t.last, path) {
- if t.options.boundaryGauge != nil {
- t.options.boundaryGauge.Inc(1)
- }
- return
- }
- // Clean up the internal dangling nodes covered by the extension node.
- // This should be done before writing the node to adhere to the committing
- // order from bottom to top.
- for _, path := range internal {
- t.options.Cleaner(path)
- }
- t.options.Writer(path, common.BytesToHash(st.val), blob)
}
// Hash will firstly hash the entire trie if it's still not hashed and then commit
-// all nodes to the associated database. Actually most of the trie nodes have been
-// committed already. The main purpose here is to commit the nodes on right boundary.
-//
-// For stack trie, Hash and Commit are functionally identical.
+// all leftover nodes to the associated database. Actually most of the trie nodes
+// have been committed already. The main purpose here is to commit the nodes on
+// right boundary.
func (t *StackTrie) Hash() common.Hash {
n := t.root
t.hash(n, nil)
return common.BytesToHash(n.val)
}
-
-// Commit will firstly hash the entire trie if it's still not hashed and then commit
-// all nodes to the associated database. Actually most of the trie nodes have been
-// committed already. The main purpose here is to commit the nodes on right boundary.
-//
-// For stack trie, Hash and Commit are functionally identical.
-func (t *StackTrie) Commit() common.Hash {
- return t.Hash()
-}
diff --git a/trie/stacktrie_fuzzer_test.go b/trie/stacktrie_fuzzer_test.go
index 1b3f9dbe9c..c8e568355c 100644
--- a/trie/stacktrie_fuzzer_test.go
+++ b/trie/stacktrie_fuzzer_test.go
@@ -42,15 +42,13 @@ func fuzz(data []byte, debugging bool) {
var (
input = bytes.NewReader(data)
spongeA = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbA = NewDatabase(rawdb.NewDatabase(spongeA), nil)
+ dbA = newTestDatabase(rawdb.NewDatabase(spongeA), rawdb.HashScheme)
trieA = NewEmpty(dbA)
spongeB = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbB = NewDatabase(rawdb.NewDatabase(spongeB), nil)
-
- options = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ 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())
})
- trieB = NewStackTrie(options)
vals []*kv
maxElements = 10000
// operate on unique keys only
@@ -87,10 +85,10 @@ func fuzz(data []byte, debugging bool) {
panic(err)
}
if nodes != nil {
- dbA.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ dbA.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
}
// Flush memdb -> disk (sponge)
- dbA.Commit(rootA, false)
+ dbA.Commit(rootA)
// Stacktrie requires sorted insertion
slices.SortFunc(vals, (*kv).cmp)
@@ -99,10 +97,9 @@ func fuzz(data []byte, debugging bool) {
if debugging {
fmt.Printf("{\"%#x\" , \"%#x\"} // stacktrie.Update\n", kv.k, kv.v)
}
- trieB.MustUpdate(kv.k, kv.v)
+ trieB.Update(kv.k, kv.v)
}
rootB := trieB.Hash()
- trieB.Commit()
if rootA != rootB {
panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB))
}
@@ -114,20 +111,19 @@ func fuzz(data []byte, debugging bool) {
// Ensure all the nodes are persisted correctly
var (
- nodeset = make(map[string][]byte) // path -> blob
- optionsC = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ nodeset = make(map[string][]byte) // path -> blob
+ trieC = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
if crypto.Keccak256Hash(blob) != hash {
panic("invalid node blob")
}
nodeset[string(path)] = common.CopyBytes(blob)
})
- trieC = NewStackTrie(optionsC)
checked int
)
for _, kv := range vals {
- trieC.MustUpdate(kv.k, kv.v)
+ trieC.Update(kv.k, kv.v)
}
- rootC := trieC.Commit()
+ rootC := trieC.Hash()
if rootA != rootC {
panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootC))
}
diff --git a/trie/stacktrie_test.go b/trie/stacktrie_test.go
index 26b5865c06..4c41b810f2 100644
--- a/trie/stacktrie_test.go
+++ b/trie/stacktrie_test.go
@@ -19,15 +19,12 @@ package trie
import (
"bytes"
"math/big"
- "math/rand"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie/testutil"
"github.com/stretchr/testify/assert"
- "golang.org/x/exp/slices"
)
func TestStackTrieInsertAndHash(t *testing.T) {
@@ -225,7 +222,7 @@ func TestStackTrieInsertAndHash(t *testing.T) {
func TestSizeBug(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -240,7 +237,7 @@ func TestSizeBug(t *testing.T) {
func TestEmptyBug(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -266,7 +263,7 @@ func TestEmptyBug(t *testing.T) {
func TestValLength56(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -291,7 +288,7 @@ func TestValLength56(t *testing.T) {
// which causes a lot of node-within-node. This case was found via fuzzing.
func TestUpdateSmallNodes(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
kvs := []struct {
K string
V string
@@ -322,7 +319,7 @@ func TestUpdateVariableKeys(t *testing.T) {
t.SkipNow()
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
kvs := []struct {
K string
V string
@@ -394,90 +391,6 @@ func TestStacktrieNotModifyValues(t *testing.T) {
}
}
-func buildPartialTree(entries []*kv, t *testing.T) map[string]common.Hash {
- var (
- options = NewStackTrieOptions()
- nodes = make(map[string]common.Hash)
- )
- var (
- first int
- last = len(entries) - 1
-
- noLeft bool
- noRight bool
- )
- // Enter split mode if there are at least two elements
- if rand.Intn(5) != 0 {
- for {
- first = rand.Intn(len(entries))
- last = rand.Intn(len(entries))
- if first <= last {
- break
- }
- }
- if first != 0 {
- noLeft = true
- }
- if last != len(entries)-1 {
- noRight = true
- }
- }
- options = options.WithSkipBoundary(noLeft, noRight, nil)
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- nodes[string(path)] = hash
- })
- tr := NewStackTrie(options)
-
- for i := first; i <= last; i++ {
- tr.MustUpdate(entries[i].k, entries[i].v)
- }
- tr.Commit()
- return nodes
-}
-
-func TestPartialStackTrie(t *testing.T) {
- for round := 0; round < 100; round++ {
- var (
- n = rand.Intn(100) + 1
- entries []*kv
- )
- for i := 0; i < n; i++ {
- var val []byte
- if rand.Intn(3) == 0 {
- val = testutil.RandBytes(3)
- } else {
- val = testutil.RandBytes(32)
- }
- entries = append(entries, &kv{
- k: testutil.RandBytes(32),
- v: val,
- })
- }
- slices.SortFunc(entries, (*kv).cmp)
-
- var (
- nodes = make(map[string]common.Hash)
- options = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- nodes[string(path)] = hash
- })
- )
- tr := NewStackTrie(options)
-
- for i := 0; i < len(entries); i++ {
- tr.MustUpdate(entries[i].k, entries[i].v)
- }
- tr.Commit()
-
- for j := 0; j < 100; j++ {
- for path, hash := range buildPartialTree(entries, t) {
- if nodes[path] != hash {
- t.Errorf("%v, want %x, got %x", []byte(path), nodes[path], hash)
- }
- }
- }
- }
-}
-
func TestStackTrieErrors(t *testing.T) {
s := NewStackTrie(nil)
// Deletion
diff --git a/trie/sync_test.go b/trie/sync_test.go
index 823fb385de..cd14f07631 100644
--- a/trie/sync_test.go
+++ b/trie/sync_test.go
@@ -32,7 +32,7 @@ import (
)
// makeTestTrie create a sample test trie to test node-wise reconstruction.
-func makeTestTrie(scheme string) (ethdb.Database, *Database, *StateTrie, map[string][]byte) {
+func makeTestTrie(scheme string) (ethdb.Database, *testDb, *StateTrie, map[string][]byte) {
// Create an empty trie
db := rawdb.NewMemoryDatabase()
triedb := newTestDatabase(db, scheme)
@@ -59,10 +59,10 @@ func makeTestTrie(scheme string) (ethdb.Database, *Database, *StateTrie, map[str
}
}
root, nodes, _ := trie.Commit(false)
- if err := triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
panic(fmt.Errorf("failed to commit db %v", err))
}
- if err := triedb.Commit(root, false); err != nil {
+ if err := triedb.Commit(root); err != nil {
panic(err)
}
// Re-create the trie based on the new state
@@ -145,7 +145,7 @@ func TestEmptySync(t *testing.T) {
emptyD, _ := New(TrieID(types.EmptyRootHash), dbD)
for i, trie := range []*Trie{emptyA, emptyB, emptyC, emptyD} {
- sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB, dbC, dbD}[i].Scheme())
+ sync := NewSync(trie.Hash(), memorydb.New(), nil, []*testDb{dbA, dbB, dbC, dbD}[i].Scheme())
if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
t.Errorf("test %d: content requested for empty trie: %v, %v, %v", i, paths, nodes, codes)
}
@@ -751,11 +751,11 @@ func testSyncOrdering(t *testing.T, scheme string) {
}
}
}
-func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database) {
+func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *testDb) {
syncWithHookWriter(t, root, db, srcDb, nil)
}
-func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database, hookWriter ethdb.KeyValueWriter) {
+func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb *testDb, hookWriter ethdb.KeyValueWriter) {
// Create a destination trie and sync with the scheduler
sched := NewSync(root, db, nil, srcDb.Scheme())
@@ -839,10 +839,10 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
diff[string(key)] = val
}
root, nodes, _ := srcTrie.Commit(false)
- if err := srcDb.Update(root, preRoot, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
panic(err)
}
- if err := srcDb.Commit(root, false); err != nil {
+ if err := srcDb.Commit(root); err != nil {
panic(err)
}
preRoot = root
@@ -864,10 +864,10 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
reverted[k] = val
}
root, nodes, _ = srcTrie.Commit(false)
- if err := srcDb.Update(root, preRoot, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
panic(err)
}
- if err := srcDb.Commit(root, false); err != nil {
+ if err := srcDb.Commit(root); err != nil {
panic(err)
}
srcTrie, _ = NewStateTrie(TrieID(root), srcDb)
@@ -922,10 +922,10 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA)
rootA, nodesA, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil {
+ if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootA, false); err != nil {
+ if err := srcTrieDB.Commit(rootA); err != nil {
panic(err)
}
// Create a destination trie and sync with the scheduler
@@ -941,10 +941,10 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateB)
rootB, nodesB, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil {
+ if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootB, false); err != nil {
+ if err := srcTrieDB.Commit(rootB); err != nil {
panic(err)
}
syncWith(t, rootB, destDisk, srcTrieDB)
@@ -959,10 +959,10 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateC)
rootC, nodesC, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil {
+ if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootC, false); err != nil {
+ if err := srcTrieDB.Commit(rootC); err != nil {
panic(err)
}
syncWith(t, rootC, destDisk, srcTrieDB)
@@ -1028,10 +1028,10 @@ func testSyncAbort(t *testing.T, scheme string) {
writeFn(key, val, srcTrie, stateA)
rootA, nodesA, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil {
+ if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootA, false); err != nil {
+ if err := srcTrieDB.Commit(rootA); err != nil {
panic(err)
}
// Create a destination trie and sync with the scheduler
@@ -1045,10 +1045,10 @@ func testSyncAbort(t *testing.T, scheme string) {
deleteFn(key, srcTrie, stateB)
rootB, nodesB, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil {
+ if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootB, false); err != nil {
+ if err := srcTrieDB.Commit(rootB); err != nil {
panic(err)
}
@@ -1072,10 +1072,10 @@ func testSyncAbort(t *testing.T, scheme string) {
writeFn(key, val, srcTrie, stateC)
rootC, nodesC, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil {
+ if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootC, false); err != nil {
+ if err := srcTrieDB.Commit(rootC); err != nil {
panic(err)
}
syncWith(t, rootC, destDisk, srcTrieDB)
diff --git a/trie/tracer_test.go b/trie/tracer_test.go
index 1c065c0b3d..3fafa8abe5 100644
--- a/trie/tracer_test.go
+++ b/trie/tracer_test.go
@@ -62,7 +62,7 @@ func TestTrieTracer(t *testing.T) {
// Tests if the trie diffs are tracked correctly. Tracer should capture
// all non-leaf dirty nodes, no matter the node is embedded or not.
func testTrieTracer(t *testing.T, vals []struct{ k, v string }) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
// Determine all new nodes are tracked
@@ -73,7 +73,7 @@ func testTrieTracer(t *testing.T, vals []struct{ k, v string }) {
insertSet := copySet(trie.tracer.inserts) // copy before commit
deleteSet := copySet(trie.tracer.deletes) // copy before commit
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
seen := setKeys(iterNodes(db, root))
if !compareSet(insertSet, seen) {
@@ -111,7 +111,8 @@ func TestTrieTracerNoop(t *testing.T) {
}
func testTrieTracerNoop(t *testing.T, vals []struct{ k, v string }) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ trie := NewEmpty(db)
for _, val := range vals {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -141,7 +142,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
t.Helper()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
orig = trie.Copy()
)
@@ -150,7 +151,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -166,7 +167,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
trie.MustUpdate([]byte(val.k), randBytes(32))
}
root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -186,7 +187,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
trie.MustUpdate(key, randBytes(32))
}
root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -202,7 +203,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
trie.MustUpdate([]byte(key), nil)
}
root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -218,7 +219,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
trie.MustUpdate([]byte(val.k), nil)
}
root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -231,7 +232,7 @@ func TestAccessListLeak(t *testing.T) {
t.Parallel()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
)
// Create trie from scratch
@@ -239,7 +240,7 @@ func TestAccessListLeak(t *testing.T) {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
var cases = []struct {
op func(tr *Trie)
@@ -285,7 +286,7 @@ func TestTinyTree(t *testing.T) {
t.Parallel()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
)
@@ -293,7 +294,7 @@ func TestTinyTree(t *testing.T) {
trie.MustUpdate([]byte(val.k), randBytes(32))
}
root, set, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(set), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(set))
parent := root
trie, _ = New(TrieID(root), db)
@@ -303,7 +304,7 @@ func TestTinyTree(t *testing.T) {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
root, set, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(set), nil)
+ db.Update(root, parent, trienode.NewWithNodeSet(set))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, set); err != nil {
@@ -342,7 +343,7 @@ func forNodes(tr *Trie) map[string][]byte {
return nodes
}
-func iterNodes(db *Database, root common.Hash) map[string][]byte {
+func iterNodes(db *testDb, root common.Hash) map[string][]byte {
tr, _ := New(TrieID(root), db)
return forNodes(tr)
}
diff --git a/trie/trie.go b/trie/trie.go
index 473c1452da..704ae3f1bb 100644
--- a/trie/trie.go
+++ b/trie/trie.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
// Trie is a Merkle Patricia Trie. Use New to create a trie that sits on
@@ -84,7 +85,7 @@ func (t *Trie) Copy() *Trie {
// zero hash or the sha3 hash of an empty string, then trie is initially
// empty, otherwise, the root node must be present in database or returns
// a MissingNodeError if not.
-func New(id *ID, db *Database) (*Trie, error) {
+func New(id *ID, db database.Database) (*Trie, error) {
reader, err := newTrieReader(id.StateRoot, id.Owner, db)
if err != nil {
return nil, err
@@ -109,7 +110,7 @@ func New(id *ID, db *Database) (*Trie, error) {
}
// NewEmpty is a shortcut to create empty tree. It's mostly used in tests.
-func NewEmpty(db *Database) *Trie {
+func NewEmpty(db database.Database) *Trie {
tr, _ := New(TrieID(types.EmptyRootHash), db)
return tr
}
diff --git a/trie/trie_reader.go b/trie/trie_reader.go
index d326a4647d..515a70737e 100644
--- a/trie/trie_reader.go
+++ b/trie/trie_reader.go
@@ -21,31 +21,19 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
-// Reader wraps the Node method of a backing trie store.
-type Reader interface {
- // Node retrieves the trie node blob with the provided trie identifier, node path and
- // the corresponding node hash. No error will be returned if the node is not found.
- //
- // When looking up nodes in the account trie, 'owner' is the zero hash. For contract
- // storage trie nodes, 'owner' is the hash of the account address that containing the
- // storage.
- //
- // TODO(rjl493456442): remove the 'hash' parameter, it's redundant in PBSS.
- Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
-}
-
// trieReader is a wrapper of the underlying node reader. It's not safe
// for concurrent usage.
type trieReader struct {
owner common.Hash
- reader Reader
+ reader database.Reader
banned map[string]struct{} // Marker to prevent node from being accessed, for tests
}
// newTrieReader initializes the trie reader with the given node reader.
-func newTrieReader(stateRoot, owner common.Hash, db *Database) (*trieReader, error) {
+func newTrieReader(stateRoot, owner common.Hash, db database.Database) (*trieReader, error) {
if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash {
if stateRoot == (common.Hash{}) {
log.Error("Zero state root hash!")
@@ -88,17 +76,22 @@ func (r *trieReader) node(path []byte, hash common.Hash) ([]byte, error) {
return blob, nil
}
-// trieLoader implements triestate.TrieLoader for constructing tries.
-type trieLoader struct {
- db *Database
+// MerkleLoader implements triestate.TrieLoader for constructing tries.
+type MerkleLoader struct {
+ db database.Database
+}
+
+// NewMerkleLoader creates the merkle trie loader.
+func NewMerkleLoader(db database.Database) *MerkleLoader {
+ return &MerkleLoader{db: db}
}
// OpenTrie opens the main account trie.
-func (l *trieLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
+func (l *MerkleLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
return New(TrieID(root), l.db)
}
// OpenStorageTrie opens the storage trie of an account.
-func (l *trieLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
+func (l *MerkleLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
return New(StorageTrieID(stateRoot, addrHash, root), l.db)
}
diff --git a/trie/trie_test.go b/trie/trie_test.go
index d0bb8c5ffa..1414cb473b 100644
--- a/trie/trie_test.go
+++ b/trie/trie_test.go
@@ -23,9 +23,9 @@ import (
"fmt"
"hash"
"io"
- "math/big"
"math/rand"
"reflect"
+ "sort"
"testing"
"testing/quick"
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -46,7 +47,7 @@ func init() {
}
func TestEmptyTrie(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
res := trie.Hash()
exp := types.EmptyRootHash
@@ -56,7 +57,7 @@ func TestEmptyTrie(t *testing.T) {
}
func TestNull(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
key := make([]byte, 32)
value := []byte("test")
trie.MustUpdate(key, value)
@@ -99,10 +100,10 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) {
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- _ = triedb.Commit(root, false)
+ _ = triedb.Commit(root)
}
trie, _ = New(TrieID(root), triedb)
@@ -180,7 +181,7 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) {
}
func TestInsert(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "doe", "reindeer")
updateString(trie, "dog", "puppy")
@@ -193,7 +194,7 @@ func TestInsert(t *testing.T) {
t.Errorf("case 1: exp %x got %x", exp, root)
}
- trie = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie = NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
@@ -204,7 +205,7 @@ func TestInsert(t *testing.T) {
}
func TestGet(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
updateString(trie, "doe", "reindeer")
updateString(trie, "dog", "puppy")
@@ -225,13 +226,14 @@ func TestGet(t *testing.T) {
return
}
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
}
}
func TestDelete(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
{"ether", "wookiedoo"},
@@ -259,7 +261,7 @@ func TestDelete(t *testing.T) {
}
func TestEmptyValues(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -284,7 +286,7 @@ func TestEmptyValues(t *testing.T) {
}
func TestReplication(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -300,7 +302,7 @@ func TestReplication(t *testing.T) {
updateString(trie, val.k, val.v)
}
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// create a new trie on top of the database and check that lookups work.
trie2, err := New(TrieID(root), db)
@@ -320,7 +322,7 @@ func TestReplication(t *testing.T) {
// recreate the trie after commit
if nodes != nil {
- db.Update(hash, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(hash, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
}
trie2, err = New(TrieID(hash), db)
if err != nil {
@@ -347,7 +349,7 @@ func TestReplication(t *testing.T) {
}
func TestLargeValue(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99})
trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32))
trie.Hash()
@@ -558,7 +560,7 @@ func runRandTest(rt randTest) error {
case opCommit:
root, nodes, _ := tr.Commit(true)
if nodes != nil {
- triedb.Update(root, origin, 0, trienode.NewWithNodeSet(nodes), nil)
+ triedb.Update(root, origin, trienode.NewWithNodeSet(nodes))
}
newtr, err := New(TrieID(root), triedb)
@@ -675,7 +677,7 @@ func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
const benchElemCount = 20000
func benchGet(b *testing.B) {
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(triedb)
k := make([]byte, 32)
@@ -696,7 +698,7 @@ func benchGet(b *testing.B) {
}
func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
k := make([]byte, 32)
b.ReportAllocs()
@@ -731,7 +733,7 @@ func BenchmarkHash(b *testing.B) {
// entries, then adding N more.
addresses, accounts := makeAccounts(2 * b.N)
// Insert the accounts into the trie and hash it
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
i := 0
for ; i < len(addresses)/2; i++ {
@@ -766,7 +768,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) {
// Make the random benchmark deterministic
addresses, accounts := makeAccounts(b.N)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -780,7 +782,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) {
func TestTinyTrie(t *testing.T) {
// Create a realistic account trie to hash
_, accounts := makeAccounts(5)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3])
if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root {
@@ -798,7 +800,7 @@ func TestTinyTrie(t *testing.T) {
if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root {
t.Errorf("3: got %x, exp %x", root, exp)
}
- checktr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ checktr := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
it := NewIterator(trie.MustNodeIterator(nil))
for it.Next() {
checktr.MustUpdate(it.Key, it.Value)
@@ -812,7 +814,7 @@ func TestTinyTrie(t *testing.T) {
func TestCommitAfterHash(t *testing.T) {
// Create a realistic account trie to hash
addresses, accounts := makeAccounts(1000)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -856,7 +858,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
numBytes := random.Uint32() % 33 // [0, 32] bytes
balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes)
- balance := new(big.Int).SetBytes(balanceBytes)
+ balance := new(uint256.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code})
accounts[i] = data
}
@@ -869,6 +871,8 @@ type spongeDb struct {
sponge hash.Hash
id string
journal []string
+ keys []string
+ values map[string]string
}
func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") }
@@ -892,13 +896,28 @@ func (s *spongeDb) Put(key []byte, value []byte) error {
valbrief = valbrief[:8]
}
s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief))
- s.sponge.Write(key)
- s.sponge.Write(value)
+ if s.values == nil {
+ s.sponge.Write(key)
+ s.sponge.Write(value)
+ } else {
+ s.keys = append(s.keys, string(key))
+ s.values[string(key)] = string(value)
+
+ }
return nil
}
func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") }
+func (s *spongeDb) Flush() {
+ // Bottom-up, the longest path first
+ sort.Sort(sort.Reverse(sort.StringSlice(s.keys)))
+ for _, key := range s.keys {
+ s.sponge.Write([]byte(key))
+ s.sponge.Write([]byte(s.values[key]))
+ }
+}
+
// spongeBatch is a dummy batch which immediately writes to the underlying spongedb
type spongeBatch struct {
db *spongeDb
@@ -923,14 +942,14 @@ func TestCommitSequence(t *testing.T) {
count int
expWriteSeqHash []byte
}{
- {20, common.FromHex("873c78df73d60e59d4a2bcf3716e8bfe14554549fea2fc147cb54129382a8066")},
- {200, common.FromHex("ba03d891bb15408c940eea5ee3d54d419595102648d02774a0268d892add9c8e")},
- {2000, common.FromHex("f7a184f20df01c94f09537401d11e68d97ad0c00115233107f51b9c287ce60c7")},
+ {20, common.FromHex("330b0afae2853d96b9f015791fbe0fb7f239bf65f335f16dfc04b76c7536276d")},
+ {200, common.FromHex("5162b3735c06b5d606b043a3ee8adbdbbb408543f4966bca9dcc63da82684eeb")},
+ {2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")},
} {
addresses, accounts := makeAccounts(tc.count)
// This spongeDb is used to check the sequence of disk-db-writes
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements
for i := 0; i < tc.count; i++ {
@@ -938,9 +957,10 @@ func TestCommitSequence(t *testing.T) {
}
// Flush trie -> database
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge)
- _ = db.Commit(root, false)
+
+ _ = 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)
@@ -955,14 +975,14 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
count int
expWriteSeqHash []byte
}{
- {20, common.FromHex("8e4a01548551d139fa9e833ebc4e66fc1ba40a4b9b7259d80db32cff7b64ebbc")},
- {200, common.FromHex("6869b4e7b95f3097a19ddb30ff735f922b915314047e041614df06958fc50554")},
- {2000, common.FromHex("444200e6f4e2df49f77752f629a96ccf7445d4698c164f962bbd85a0526ef424")},
+ {20, common.FromHex("8016650c7a50cf88485fd06cde52d634a89711051107f00d21fae98234f2f13d")},
+ {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
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements
for i := 0; i < tc.count; i++ {
@@ -982,9 +1002,10 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
}
// Flush trie -> database
root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge)
- _ = db.Commit(root, false)
+
+ _ = db.Commit(root)
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
@@ -996,17 +1017,24 @@ func TestCommitSequenceStackTrie(t *testing.T) {
for count := 1; count < 200; count++ {
prng := rand.New(rand.NewSource(int64(count)))
// This spongeDb is used to check the sequence of disk-db-writes
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "a",
+ values: make(map[string]string),
+ }
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
- // Another sponge is used for the stacktrie commits
- stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"}
- options := NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ // Another sponge is used for the stacktrie commits
+ stackTrieSponge := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "b",
+ values: make(map[string]string),
+ }
+ stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme())
})
- stTrie := NewStackTrie(options)
+
// Fill the trie with elements
for i := 0; i < count; i++ {
// For the stack trie, we need to do inserts in proper order
@@ -1028,14 +1056,17 @@ func TestCommitSequenceStackTrie(t *testing.T) {
// Flush trie -> database
root, nodes, _ := trie.Commit(false)
// Flush memdb -> disk (sponge)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- db.Commit(root, false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ db.Commit(root)
+ s.Flush()
+
// And flush stacktrie -> disk
- stRoot := stTrie.Commit()
+ stRoot := stTrie.Hash()
if stRoot != root {
t.Fatalf("root wrong, got %x exp %x", stRoot, root)
}
+ stackTrieSponge.Flush()
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
// Show the journal
t.Logf("Expected:")
@@ -1062,17 +1093,23 @@ func TestCommitSequenceStackTrie(t *testing.T) {
// that even a small trie which contains a leaf will have an extension making it
// not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do.
func TestCommitSequenceSmallRoot(t *testing.T) {
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "a",
+ values: make(map[string]string),
+ }
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
- // Another sponge is used for the stacktrie commits
- stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"}
- options := NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ // Another sponge is used for the stacktrie commits
+ stackTrieSponge := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "b",
+ values: make(map[string]string),
+ }
+ stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme())
})
- stTrie := NewStackTrie(options)
// Add a single small-element to the trie(s)
key := make([]byte, 5)
key[0] = 1
@@ -1081,16 +1118,18 @@ func TestCommitSequenceSmallRoot(t *testing.T) {
// Flush trie -> database
root, nodes, _ := trie.Commit(false)
// Flush memdb -> disk (sponge)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- db.Commit(root, false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ db.Commit(root)
+
// And flush stacktrie -> disk
- stRoot := stTrie.Commit()
+ stRoot := stTrie.Hash()
if stRoot != root {
t.Fatalf("root wrong, got %x exp %x", stRoot, root)
}
-
t.Logf("root: %x\n", stRoot)
+ s.Flush()
+ stackTrieSponge.Flush()
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp)
}
@@ -1146,7 +1185,7 @@ func BenchmarkHashFixedSize(b *testing.B) {
func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
b.ReportAllocs()
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -1202,7 +1241,7 @@ func BenchmarkCommitAfterHashFixedSize(b *testing.B) {
func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
b.ReportAllocs()
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -1213,67 +1252,6 @@ func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accou
b.StopTimer()
}
-func BenchmarkDerefRootFixedSize(b *testing.B) {
- b.Run("10", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(20)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("100", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(100)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
-
- b.Run("1K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(1000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("10K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(10000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("100K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(100000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
-}
-
-func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
- b.ReportAllocs()
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
- trie := NewEmpty(triedb)
-
- for i := 0; i < len(addresses); i++ {
- trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
- }
-
- h := trie.Hash()
- root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- b.StartTimer()
- triedb.Dereference(h)
- b.StopTimer()
-}
-
func getString(trie *Trie, k string) []byte {
return trie.MustGet([]byte(k))
}
diff --git a/trie/verkle.go b/trie/verkle.go
index 89e2e53408..01d813d9ec 100644
--- a/trie/verkle.go
+++ b/trie/verkle.go
@@ -20,13 +20,13 @@ import (
"encoding/binary"
"errors"
"fmt"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/ethereum/go-ethereum/triedb/database"
"github.com/gballet/go-verkle"
"github.com/holiman/uint256"
)
@@ -40,13 +40,12 @@ var (
// interface so that Verkle trees can be reused verbatim.
type VerkleTrie struct {
root verkle.VerkleNode
- db *Database
cache *utils.PointCache
reader *trieReader
}
// NewVerkleTrie constructs a verkle tree based on the specified root hash.
-func NewVerkleTrie(root common.Hash, db *Database, cache *utils.PointCache) (*VerkleTrie, error) {
+func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCache) (*VerkleTrie, error) {
reader, err := newTrieReader(root, common.Hash{}, db)
if err != nil {
return nil, err
@@ -65,7 +64,6 @@ func NewVerkleTrie(root common.Hash, db *Database, cache *utils.PointCache) (*Ve
}
return &VerkleTrie{
root: node,
- db: db,
cache: cache,
reader: reader,
}, nil
@@ -108,7 +106,7 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error
for i := 0; i < len(balance)/2; i++ {
balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1]
}
- acc.Balance = new(big.Int).SetBytes(balance[:])
+ acc.Balance = new(uint256.Int).SetBytes32(balance[:])
// Decode codehash
acc.CodeHash = values[utils.CodeKeccakLeafKey]
@@ -262,7 +260,6 @@ func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
func (t *VerkleTrie) Copy() *VerkleTrie {
return &VerkleTrie{
root: t.root.Copy(),
- db: t.db,
cache: t.cache,
reader: t.reader,
}
diff --git a/trie/verkle_test.go b/trie/verkle_test.go
index bd31ea3879..0cbe28bf01 100644
--- a/trie/verkle_test.go
+++ b/trie/verkle_test.go
@@ -18,27 +18,26 @@ package trie
import (
"bytes"
- "math/big"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/holiman/uint256"
)
var (
accounts = map[common.Address]*types.StateAccount{
{1}: {
Nonce: 100,
- Balance: big.NewInt(100),
+ Balance: uint256.NewInt(100),
CodeHash: common.Hash{0x1}.Bytes(),
},
{2}: {
Nonce: 200,
- Balance: big.NewInt(200),
+ Balance: uint256.NewInt(200),
CodeHash: common.Hash{0x2}.Bytes(),
},
}
@@ -57,12 +56,7 @@ var (
)
func TestVerkleTreeReadWrite(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), &Config{
- IsVerkle: true,
- PathDB: pathdb.Defaults,
- })
- defer db.Close()
-
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme)
tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100))
for addr, acct := range accounts {
diff --git a/trie/database.go b/triedb/database.go
similarity index 91%
rename from trie/database.go
rename to triedb/database.go
index e20f7ef903..939a21f147 100644
--- a/trie/database.go
+++ b/triedb/database.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package trie
+package triedb
import (
"errors"
@@ -22,10 +22,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb/database"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// Config defines all necessary options for database.
@@ -108,14 +110,21 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
if config.PathDB != nil {
db.backend = pathdb.New(diskdb, config.PathDB)
} else {
- db.backend = hashdb.New(diskdb, config.HashDB, mptResolver{})
+ var resolver hashdb.ChildResolver
+ if config.IsVerkle {
+ // TODO define verkle resolver
+ log.Crit("Verkle node resolver is not defined")
+ } else {
+ resolver = trie.MerkleResolver{}
+ }
+ db.backend = hashdb.New(diskdb, config.HashDB, resolver)
}
return db
}
// Reader returns a reader for accessing all trie nodes with provided state root.
// An error will be returned if the requested state is not available.
-func (db *Database) Reader(blockRoot common.Hash) (Reader, error) {
+func (db *Database) Reader(blockRoot common.Hash) (database.Reader, error) {
switch b := db.backend.(type) {
case *hashdb.Database:
return b.Reader(blockRoot)
@@ -190,8 +199,7 @@ func (db *Database) WritePreimages() {
}
}
-// Preimage retrieves a cached trie node pre-image from memory. If it cannot be
-// found cached, the method queries the persistent database for the content.
+// Preimage retrieves a cached trie node pre-image from preimage store.
func (db *Database) Preimage(hash common.Hash) []byte {
if db.preimages == nil {
return nil
@@ -199,6 +207,14 @@ func (db *Database) Preimage(hash common.Hash) []byte {
return db.preimages.preimage(hash)
}
+// InsertPreimage writes pre-images of trie node to the preimage store.
+func (db *Database) InsertPreimage(preimages map[common.Hash][]byte) {
+ if db.preimages == nil {
+ return
+ }
+ db.preimages.insertPreimage(preimages)
+}
+
// Cap iteratively flushes old but still referenced trie nodes until the total
// memory usage goes below the given threshold. The held pre-images accumulated
// up to this point will be flushed in case the size exceeds the threshold.
@@ -249,7 +265,14 @@ func (db *Database) Recover(target common.Hash) error {
if !ok {
return errors.New("not supported")
}
- return pdb.Recover(target, &trieLoader{db: db})
+ var loader triestate.TrieLoader
+ if db.config.IsVerkle {
+ // TODO define verkle loader
+ log.Crit("Verkle loader is not defined")
+ } else {
+ loader = trie.NewMerkleLoader(db)
+ }
+ return pdb.Recover(target, loader)
}
// Recoverable returns the indicator if the specified state is enabled to be
diff --git a/triedb/database/database.go b/triedb/database/database.go
new file mode 100644
index 0000000000..18a8f454e2
--- /dev/null
+++ b/triedb/database/database.go
@@ -0,0 +1,48 @@
+// Copyright 2024 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 database
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Reader wraps the Node method of a backing trie reader.
+type Reader interface {
+ // Node retrieves the trie node blob with the provided trie identifier,
+ // node path and the corresponding node hash. No error will be returned
+ // if the node is not found.
+ Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
+}
+
+// PreimageStore wraps the methods of a backing store for reading and writing
+// trie node preimages.
+type PreimageStore interface {
+ // Preimage retrieves the preimage of the specified hash.
+ Preimage(hash common.Hash) []byte
+
+ // InsertPreimage commits a set of preimages along with their hashes.
+ InsertPreimage(preimages map[common.Hash][]byte)
+}
+
+// Database wraps the methods of a backing trie store.
+type Database interface {
+ PreimageStore
+
+ // Reader returns a node reader associated with the specific state.
+ // An error will be returned if the specified state is not available.
+ Reader(stateRoot common.Hash) (Reader, error)
+}
diff --git a/trie/triedb/hashdb/database.go b/triedb/hashdb/database.go
similarity index 100%
rename from trie/triedb/hashdb/database.go
rename to triedb/hashdb/database.go
diff --git a/trie/triedb/pathdb/database.go b/triedb/pathdb/database.go
similarity index 94%
rename from trie/triedb/pathdb/database.go
rename to triedb/pathdb/database.go
index dc64414e9b..f2d6cea635 100644
--- a/trie/triedb/pathdb/database.go
+++ b/triedb/pathdb/database.go
@@ -170,14 +170,31 @@ func New(diskdb ethdb.Database, config *Config) *Database {
}
db.freezer = freezer
- // Truncate the extra state histories above in freezer in case
- // it's not aligned with the disk layer.
- pruned, err := truncateFromHead(db.diskdb, freezer, db.tree.bottom().stateID())
- if err != nil {
- log.Crit("Failed to truncate extra state histories", "err", err)
- }
- if pruned != 0 {
- log.Warn("Truncated extra state histories", "number", pruned)
+ diskLayerID := db.tree.bottom().stateID()
+ if diskLayerID == 0 {
+ // Reset the entire state histories in case the trie database is
+ // not initialized yet, as these state histories are not expected.
+ frozen, err := db.freezer.Ancients()
+ if err != nil {
+ log.Crit("Failed to retrieve head of state history", "err", err)
+ }
+ if frozen != 0 {
+ err := db.freezer.Reset()
+ if err != nil {
+ log.Crit("Failed to reset state histories", "err", err)
+ }
+ log.Info("Truncated extraneous state history")
+ }
+ } else {
+ // Truncate the extra state histories above in freezer in case
+ // it's not aligned with the disk layer.
+ pruned, err := truncateFromHead(db.diskdb, freezer, diskLayerID)
+ if err != nil {
+ log.Crit("Failed to truncate extra state histories", "err", err)
+ }
+ if pruned != 0 {
+ log.Warn("Truncated extra state histories", "number", pruned)
+ }
}
}
// Disable database in case node is still in the initial state sync stage.
@@ -431,6 +448,9 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
inited = true
}
})
+ if !inited {
+ inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
+ }
return inited
}
diff --git a/trie/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go
similarity index 99%
rename from trie/triedb/pathdb/database_test.go
rename to triedb/pathdb/database_test.go
index f2e68d3473..699ac421c5 100644
--- a/trie/triedb/pathdb/database_test.go
+++ b/triedb/pathdb/database_test.go
@@ -20,7 +20,6 @@ import (
"bytes"
"errors"
"fmt"
- "math/big"
"math/rand"
"testing"
@@ -32,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/trie/testutil"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
@@ -53,7 +53,7 @@ func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[comm
func generateAccount(storageRoot common.Hash) types.StateAccount {
return types.StateAccount{
Nonce: uint64(rand.Intn(100)),
- Balance: big.NewInt(rand.Int63()),
+ Balance: uint256.NewInt(rand.Uint64()),
CodeHash: testutil.RandBytes(32),
Root: storageRoot,
}
diff --git a/trie/triedb/pathdb/difflayer.go b/triedb/pathdb/difflayer.go
similarity index 100%
rename from trie/triedb/pathdb/difflayer.go
rename to triedb/pathdb/difflayer.go
diff --git a/trie/triedb/pathdb/difflayer_test.go b/triedb/pathdb/difflayer_test.go
similarity index 100%
rename from trie/triedb/pathdb/difflayer_test.go
rename to triedb/pathdb/difflayer_test.go
diff --git a/trie/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go
similarity index 100%
rename from trie/triedb/pathdb/disklayer.go
rename to triedb/pathdb/disklayer.go
diff --git a/trie/triedb/pathdb/errors.go b/triedb/pathdb/errors.go
similarity index 100%
rename from trie/triedb/pathdb/errors.go
rename to triedb/pathdb/errors.go
diff --git a/trie/triedb/pathdb/history.go b/triedb/pathdb/history.go
similarity index 100%
rename from trie/triedb/pathdb/history.go
rename to triedb/pathdb/history.go
diff --git a/trie/triedb/pathdb/history_test.go b/triedb/pathdb/history_test.go
similarity index 100%
rename from trie/triedb/pathdb/history_test.go
rename to triedb/pathdb/history_test.go
diff --git a/trie/triedb/pathdb/journal.go b/triedb/pathdb/journal.go
similarity index 100%
rename from trie/triedb/pathdb/journal.go
rename to triedb/pathdb/journal.go
diff --git a/trie/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go
similarity index 100%
rename from trie/triedb/pathdb/layertree.go
rename to triedb/pathdb/layertree.go
diff --git a/trie/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go
similarity index 100%
rename from trie/triedb/pathdb/metrics.go
rename to triedb/pathdb/metrics.go
diff --git a/trie/triedb/pathdb/nodebuffer.go b/triedb/pathdb/nodebuffer.go
similarity index 100%
rename from trie/triedb/pathdb/nodebuffer.go
rename to triedb/pathdb/nodebuffer.go
diff --git a/trie/triedb/pathdb/testutils.go b/triedb/pathdb/testutils.go
similarity index 100%
rename from trie/triedb/pathdb/testutils.go
rename to triedb/pathdb/testutils.go
diff --git a/trie/preimages.go b/triedb/preimages.go
similarity index 99%
rename from trie/preimages.go
rename to triedb/preimages.go
index d7e5f8729d..54b3859000 100644
--- a/trie/preimages.go
+++ b/triedb/preimages.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package trie
+package triedb
import (
"sync"