mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
Merge tag 'v1.13.5' of https://github.com/ethereum/go-ethereum into shivam/upstream-geth-1.13.5
This commit is contained in:
commit
a9fa325b7e
531 changed files with 20171 additions and 18971 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -57,3 +57,6 @@ dist
|
||||||
.dccache
|
.dccache
|
||||||
|
|
||||||
*.csv
|
*.csv
|
||||||
|
logs/
|
||||||
|
|
||||||
|
tests/spec-tests/
|
||||||
|
|
|
||||||
44
.travis.yml
44
.travis.yml
|
|
@ -13,7 +13,7 @@ jobs:
|
||||||
- stage: lint
|
- stage: lint
|
||||||
os: linux
|
os: linux
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- lint
|
- lint
|
||||||
git:
|
git:
|
||||||
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- docker
|
- docker
|
||||||
services:
|
services:
|
||||||
|
|
@ -45,7 +45,7 @@ jobs:
|
||||||
os: linux
|
os: linux
|
||||||
arch: arm64
|
arch: arm64
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- docker
|
- docker
|
||||||
services:
|
services:
|
||||||
|
|
@ -87,10 +87,9 @@ jobs:
|
||||||
os: linux
|
os: linux
|
||||||
dist: bionic
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- azure-linux
|
- azure-linux
|
||||||
- GO111MODULE=on
|
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
addons:
|
addons:
|
||||||
|
|
@ -159,26 +158,26 @@ jobs:
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
os: osx
|
os: osx
|
||||||
go: 1.20.x
|
osx_image: xcode14.2
|
||||||
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- azure-osx
|
- azure-osx
|
||||||
- GO111MODULE=on
|
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
|
- go run build/ci.go install -dlgo -arch arm64
|
||||||
|
- go run build/ci.go archive -arch arm64 -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
|
|
||||||
# These builders run the tests
|
# These builders run the tests
|
||||||
- stage: build
|
- stage: build
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
|
||||||
- GO111MODULE=on
|
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go test $TEST_PACKAGES
|
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
|
||||||
|
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = pull_request
|
if: type = pull_request
|
||||||
|
|
@ -186,20 +185,24 @@ jobs:
|
||||||
arch: arm64
|
arch: arm64
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.20.x
|
||||||
env:
|
|
||||||
- GO111MODULE=on
|
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go test $TEST_PACKAGES
|
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
|
||||||
|
|
||||||
|
- stage: build
|
||||||
|
os: linux
|
||||||
|
dist: bionic
|
||||||
|
go: 1.20.x
|
||||||
|
script:
|
||||||
|
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
|
||||||
|
|
||||||
# This builder does the Ubuntu PPA nightly uploads
|
# This builder does the Ubuntu PPA nightly uploads
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = cron || (type = push && tag ~= /^v[0-9]/)
|
if: type = cron || (type = push && tag ~= /^v[0-9]/)
|
||||||
os: linux
|
os: linux
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.18.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- ubuntu-ppa
|
- ubuntu-ppa
|
||||||
- GO111MODULE=on
|
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
addons:
|
addons:
|
||||||
|
|
@ -220,10 +223,9 @@ jobs:
|
||||||
if: type = cron
|
if: type = cron
|
||||||
os: linux
|
os: linux
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
env:
|
||||||
- azure-purge
|
- azure-purge
|
||||||
- GO111MODULE=on
|
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
script:
|
script:
|
||||||
|
|
@ -234,9 +236,7 @@ jobs:
|
||||||
if: type = cron
|
if: type = cron
|
||||||
os: linux
|
os: linux
|
||||||
dist: bionic
|
dist: bionic
|
||||||
go: 1.20.x
|
go: 1.21.x
|
||||||
env:
|
|
||||||
- GO111MODULE=on
|
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go test -race $TEST_PACKAGES
|
- travis_wait 30 go run build/ci.go test -race $TEST_PACKAGES
|
||||||
|
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -89,7 +89,7 @@ docs:
|
||||||
$(GORUN) cmd/clidoc/main.go -d ./docs/cli
|
$(GORUN) cmd/clidoc/main.go -d ./docs/cli
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
env GO111MODULE=on go clean -cache
|
go clean -cache
|
||||||
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
||||||
|
|
||||||
# The devtools target installs tools required for 'go generate'.
|
# The devtools target installs tools required for 'go generate'.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -269,29 +270,65 @@ func (abi *ABI) HasReceive() bool {
|
||||||
// revertSelector is a special function selector for revert reason unpacking.
|
// revertSelector is a special function selector for revert reason unpacking.
|
||||||
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
|
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
|
||||||
|
|
||||||
|
// panicSelector is a special function selector for panic reason unpacking.
|
||||||
|
var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4]
|
||||||
|
|
||||||
|
// panicReasons map is for readable panic codes
|
||||||
|
// see this linkage for the deails
|
||||||
|
// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
|
||||||
|
// the reason string list is copied from ether.js
|
||||||
|
// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218
|
||||||
|
var panicReasons = map[uint64]string{
|
||||||
|
0x00: "generic panic",
|
||||||
|
0x01: "assert(false)",
|
||||||
|
0x11: "arithmetic underflow or overflow",
|
||||||
|
0x12: "division or modulo by zero",
|
||||||
|
0x21: "enum overflow",
|
||||||
|
0x22: "invalid encoded storage byte array accessed",
|
||||||
|
0x31: "out-of-bounds array access; popping on an empty array",
|
||||||
|
0x32: "out-of-bounds access of an array or bytesN",
|
||||||
|
0x41: "out of memory",
|
||||||
|
0x51: "uninitialized function",
|
||||||
|
}
|
||||||
|
|
||||||
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
|
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
|
||||||
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
|
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
|
||||||
// the provided revert reason is abi-encoded as if it were a call to a function
|
// the provided revert reason is abi-encoded as if it were a call to function
|
||||||
// `Error(string)`. So it's a special tool for it.
|
// `Error(string)` or `Panic(uint256)`. So it's a special tool for it.
|
||||||
func UnpackRevert(data []byte) (string, error) {
|
func UnpackRevert(data []byte) (string, error) {
|
||||||
if len(data) < 4 {
|
if len(data) < 4 {
|
||||||
return "", errors.New("invalid data for unpacking")
|
return "", errors.New("invalid data for unpacking")
|
||||||
}
|
}
|
||||||
|
switch {
|
||||||
if !bytes.Equal(data[:4], revertSelector) {
|
case bytes.Equal(data[:4], revertSelector):
|
||||||
|
typ, err := NewType("string", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return unpacked[0].(string), nil
|
||||||
|
case bytes.Equal(data[:4], panicSelector):
|
||||||
|
typ, err := NewType("uint256", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pCode := unpacked[0].(*big.Int)
|
||||||
|
// uint64 safety check for future
|
||||||
|
// but the code is not bigger than MAX(uint64) now
|
||||||
|
if pCode.IsUint64() {
|
||||||
|
if reason, ok := panicReasons[pCode.Uint64()]; ok {
|
||||||
|
return reason, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("unknown panic code: %#x", pCode), nil
|
||||||
|
default:
|
||||||
return "", errors.New("invalid data for unpacking")
|
return "", errors.New("invalid data for unpacking")
|
||||||
}
|
}
|
||||||
|
|
||||||
typ, err := NewType("string", "", nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unpacked[0].(string), nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1277,6 +1277,8 @@ func TestUnpackRevert(t *testing.T) {
|
||||||
{"", "", errors.New("invalid data for unpacking")},
|
{"", "", errors.New("invalid data for unpacking")},
|
||||||
{"08c379a1", "", errors.New("invalid data for unpacking")},
|
{"08c379a1", "", errors.New("invalid data for unpacking")},
|
||||||
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
|
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
|
||||||
|
{"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil},
|
||||||
|
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
for index, c := range cases {
|
for index, c := range cases {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ var (
|
||||||
// on a backend that doesn't implement PendingContractCaller.
|
// on a backend that doesn't implement PendingContractCaller.
|
||||||
ErrNoPendingState = errors.New("backend does not support pending state")
|
ErrNoPendingState = errors.New("backend does not support pending state")
|
||||||
|
|
||||||
|
// ErrNoBlockHashState is raised when attempting to perform a block hash action
|
||||||
|
// on a backend that doesn't implement BlockHashContractCaller.
|
||||||
|
ErrNoBlockHashState = errors.New("backend does not support block hash state")
|
||||||
|
|
||||||
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
||||||
// an empty contract behind.
|
// an empty contract behind.
|
||||||
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
||||||
|
|
@ -64,6 +68,17 @@ type PendingContractCaller interface {
|
||||||
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
|
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
|
||||||
|
// Call will try to discover this interface when access to a block by hash is requested.
|
||||||
|
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
|
||||||
|
type BlockHashContractCaller interface {
|
||||||
|
// CodeAtHash returns the code of the given account in the state at the specified block hash.
|
||||||
|
CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
|
// CallContractAtHash executes an Ethereum contract all against the state at the specified block hash.
|
||||||
|
CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ContractTransactor defines the methods needed to allow operating with a contract
|
// ContractTransactor defines the methods needed to allow operating with a contract
|
||||||
// on a write only basis. Besides the transacting method, the remainder are helpers
|
// on a write only basis. Besides the transacting method, the remainder are helpers
|
||||||
// used when the user does not provide some needed values, but rather leaves it up
|
// used when the user does not provide some needed values, but rather leaves it up
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
|
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")
|
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
|
||||||
errTransactionDoesNotExist = errors.New("transaction does not exist")
|
errTransactionDoesNotExist = errors.New("transaction does not exist")
|
||||||
)
|
)
|
||||||
|
|
@ -199,6 +200,23 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return stateDB.GetCode(contract), nil
|
||||||
}
|
}
|
||||||
|
|
@ -212,7 +230,6 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Addres
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return stateDB.GetBalance(contract), nil
|
return stateDB.GetBalance(contract), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +242,6 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return stateDB.GetNonce(contract), nil
|
return stateDB.GetNonce(contract), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +254,6 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
val := stateDB.GetState(contract, key)
|
val := stateDB.GetState(contract, key)
|
||||||
return val[:], nil
|
return val[:], nil
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +339,11 @@ func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (
|
||||||
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
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() {
|
if hash == b.pendingBlock.Hash() {
|
||||||
return b.pendingBlock.Header(), nil
|
return b.pendingBlock.Header(), nil
|
||||||
}
|
}
|
||||||
|
|
@ -440,6 +459,22 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
|
||||||
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
|
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
|
||||||
return nil, errBlockNumberUnsupported
|
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()
|
stateDB, err := b.blockchain.State()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -590,7 +625,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if failed {
|
if failed {
|
||||||
if result != nil && result.Err != vm.ErrOutOfGas {
|
if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) {
|
||||||
if len(result.Revert()) > 0 {
|
if len(result.Revert()) > 0 {
|
||||||
return 0, newRevertError(result)
|
return 0, newRevertError(result)
|
||||||
}
|
}
|
||||||
|
|
@ -610,8 +645,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||||
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
|
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
|
||||||
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||||
}
|
}
|
||||||
head := b.blockchain.CurrentHeader()
|
if !b.blockchain.Config().IsLondon(header.Number) {
|
||||||
if !b.blockchain.Config().IsLondon(head.Number) {
|
|
||||||
// If there's no basefee, then it must be a non-1559 execution
|
// If there's no basefee, then it must be a non-1559 execution
|
||||||
if call.GasPrice == nil {
|
if call.GasPrice == nil {
|
||||||
call.GasPrice = new(big.Int)
|
call.GasPrice = new(big.Int)
|
||||||
|
|
@ -633,13 +667,13 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||||
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
|
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
|
||||||
call.GasPrice = new(big.Int)
|
call.GasPrice = new(big.Int)
|
||||||
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
|
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
|
||||||
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
|
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ensure message is initialized properly.
|
// Ensure message is initialized properly.
|
||||||
if call.Gas == 0 {
|
if call.Gas == 0 {
|
||||||
call.Gas = 50000000
|
call.Gas = 10 * header.GasLimit
|
||||||
}
|
}
|
||||||
if call.Value == nil {
|
if call.Value == nil {
|
||||||
call.Value = new(big.Int)
|
call.Value = new(big.Int)
|
||||||
|
|
@ -700,8 +734,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
|
||||||
}
|
}
|
||||||
block.AddTxWithChain(b.blockchain, tx)
|
block.AddTxWithChain(b.blockchain, tx)
|
||||||
})
|
})
|
||||||
stateDB, _ := b.blockchain.State()
|
stateDB, err := b.blockchain.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
b.pendingBlock = blocks[0]
|
b.pendingBlock = blocks[0]
|
||||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
||||||
b.pendingReceipts = receipts[0]
|
b.pendingReceipts = receipts[0]
|
||||||
|
|
@ -821,11 +857,12 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
|
||||||
blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
|
blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
|
||||||
block.OffsetTime(int64(adjustment.Seconds()))
|
block.OffsetTime(int64(adjustment.Seconds()))
|
||||||
})
|
})
|
||||||
stateDB, _ := b.blockchain.State()
|
stateDB, err := b.blockchain.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
b.pendingBlock = blocks[0]
|
b.pendingBlock = blocks[0]
|
||||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -892,7 +929,7 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
|
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
|
||||||
logs := rawdb.ReadLogs(fb.db, hash, number, fb.bc.Config())
|
logs := rawdb.ReadLogs(fb.db, hash, number)
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1090,6 +1090,43 @@ func TestCodeAt(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCodeAtHash(t *testing.T) {
|
||||||
|
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:
|
// 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]}
|
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
|
||||||
|
|
@ -1137,7 +1174,7 @@ func TestPendingAndCallContract(t *testing.T) {
|
||||||
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
sim.Commit()
|
blockHash := sim.Commit()
|
||||||
|
|
||||||
// make sure you can call the contract
|
// make sure you can call the contract
|
||||||
res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
|
res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
|
||||||
|
|
@ -1156,6 +1193,23 @@ func TestPendingAndCallContract(t *testing.T) {
|
||||||
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
|
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))
|
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:
|
// This test is based on the following contract:
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ type CallOpts struct {
|
||||||
Pending bool // Whether to operate on the pending state or the last known one
|
Pending bool // Whether to operate on the pending state or the last known one
|
||||||
From common.Address // Optional the sender address, otherwise the first account is used
|
From common.Address // Optional the sender address, otherwise the first account is used
|
||||||
BlockNumber *big.Int // Optional the block number on which the call should be performed
|
BlockNumber *big.Int // Optional the block number on which the call should be performed
|
||||||
|
BlockHash common.Hash // Optional the block hash on which the call should be performed
|
||||||
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,6 +201,23 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
|
||||||
return ErrNoCode
|
return ErrNoCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if opts.BlockHash != (common.Hash{}) {
|
||||||
|
bh, ok := c.caller.(BlockHashContractCaller)
|
||||||
|
if !ok {
|
||||||
|
return ErrNoBlockHashState
|
||||||
|
}
|
||||||
|
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(output) == 0 {
|
||||||
|
// Make sure we have a contract to operate on, and bail out otherwise.
|
||||||
|
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(code) == 0 {
|
||||||
|
return ErrNoCode
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,26 @@ func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ether
|
||||||
return mc.pendingCallContractBytes, mc.pendingCallContractErr
|
return mc.pendingCallContractBytes, mc.pendingCallContractErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mockBlockHashCaller struct {
|
||||||
|
*mockCaller
|
||||||
|
codeAtHashBytes []byte
|
||||||
|
codeAtHashErr error
|
||||||
|
codeAtHashCalled bool
|
||||||
|
callContractAtHashCalled bool
|
||||||
|
callContractAtHashBytes []byte
|
||||||
|
callContractAtHashErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) {
|
||||||
|
mc.codeAtHashCalled = true
|
||||||
|
return mc.codeAtHashBytes, mc.codeAtHashErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) {
|
||||||
|
mc.callContractAtHashCalled = true
|
||||||
|
return mc.callContractAtHashBytes, mc.callContractAtHashErr
|
||||||
|
}
|
||||||
|
|
||||||
func TestPassingBlockNumber(t *testing.T) {
|
func TestPassingBlockNumber(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
@ -414,6 +434,15 @@ func TestCall(t *testing.T) {
|
||||||
Pending: true,
|
Pending: true,
|
||||||
},
|
},
|
||||||
method: method,
|
method: method,
|
||||||
|
}, {
|
||||||
|
name: "ok hash",
|
||||||
|
mc: &mockBlockHashCaller{
|
||||||
|
codeAtHashBytes: []byte{0},
|
||||||
|
},
|
||||||
|
opts: &bind.CallOpts{
|
||||||
|
BlockHash: common.Hash{0xaa},
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
}, {
|
}, {
|
||||||
name: "pack error, no method",
|
name: "pack error, no method",
|
||||||
mc: new(mockCaller),
|
mc: new(mockCaller),
|
||||||
|
|
@ -427,6 +456,14 @@ func TestCall(t *testing.T) {
|
||||||
},
|
},
|
||||||
method: method,
|
method: method,
|
||||||
wantErrExact: bind.ErrNoPendingState,
|
wantErrExact: bind.ErrNoPendingState,
|
||||||
|
}, {
|
||||||
|
name: "interface error, blockHash but not a BlockHashContractCaller",
|
||||||
|
mc: new(mockCaller),
|
||||||
|
opts: &bind.CallOpts{
|
||||||
|
BlockHash: common.Hash{0xaa},
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
|
wantErrExact: bind.ErrNoBlockHashState,
|
||||||
}, {
|
}, {
|
||||||
name: "pending call canceled",
|
name: "pending call canceled",
|
||||||
mc: &mockPendingCaller{
|
mc: &mockPendingCaller{
|
||||||
|
|
@ -474,6 +511,34 @@ func TestCall(t *testing.T) {
|
||||||
mc: new(mockCaller),
|
mc: new(mockCaller),
|
||||||
method: method,
|
method: method,
|
||||||
wantErrExact: bind.ErrNoCode,
|
wantErrExact: bind.ErrNoCode,
|
||||||
|
}, {
|
||||||
|
name: "call contract at hash error",
|
||||||
|
mc: &mockBlockHashCaller{
|
||||||
|
callContractAtHashErr: context.DeadlineExceeded,
|
||||||
|
},
|
||||||
|
opts: &bind.CallOpts{
|
||||||
|
BlockHash: common.Hash{0xaa},
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
|
wantErrExact: context.DeadlineExceeded,
|
||||||
|
}, {
|
||||||
|
name: "code at error",
|
||||||
|
mc: &mockBlockHashCaller{
|
||||||
|
codeAtHashErr: errors.New(""),
|
||||||
|
},
|
||||||
|
opts: &bind.CallOpts{
|
||||||
|
BlockHash: common.Hash{0xaa},
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
|
wantErr: true,
|
||||||
|
}, {
|
||||||
|
name: "no code at hash",
|
||||||
|
mc: new(mockBlockHashCaller),
|
||||||
|
opts: &bind.CallOpts{
|
||||||
|
BlockHash: common.Hash{0xaa},
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
|
wantErrExact: bind.ErrNoCode,
|
||||||
}, {
|
}, {
|
||||||
name: "unpack error missing arg",
|
name: "unpack error missing arg",
|
||||||
mc: &mockCaller{
|
mc: &mockCaller{
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,12 @@ func NewMethod(name string, rawName string, funType FunctionType, mutability str
|
||||||
}
|
}
|
||||||
|
|
||||||
identity := fmt.Sprintf("function %v", rawName)
|
identity := fmt.Sprintf("function %v", rawName)
|
||||||
if funType == Fallback {
|
switch funType {
|
||||||
|
case Fallback:
|
||||||
identity = "fallback"
|
identity = "fallback"
|
||||||
} else if funType == Receive {
|
case Receive:
|
||||||
identity = "receive"
|
identity = "receive"
|
||||||
} else if funType == Constructor {
|
case Constructor:
|
||||||
identity = "constructor"
|
identity = "constructor"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,12 @@ func TestMethodString(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
var got string
|
var got string
|
||||||
if test.method == "fallback" {
|
switch test.method {
|
||||||
|
case "fallback":
|
||||||
got = abi.Fallback.String()
|
got = abi.Fallback.String()
|
||||||
} else if test.method == "receive" {
|
case "receive":
|
||||||
got = abi.Receive.String()
|
got = abi.Receive.String()
|
||||||
} else {
|
default:
|
||||||
got = abi.Methods[test.method].String()
|
got = abi.Methods[test.method].String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,13 +176,14 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
|
||||||
// this value will become our slice or our array, depending on the type
|
// this value will become our slice or our array, depending on the type
|
||||||
var refSlice reflect.Value
|
var refSlice reflect.Value
|
||||||
|
|
||||||
if t.T == SliceTy {
|
switch t.T {
|
||||||
|
case SliceTy:
|
||||||
// declare our slice
|
// declare our slice
|
||||||
refSlice = reflect.MakeSlice(t.GetType(), size, size)
|
refSlice = reflect.MakeSlice(t.GetType(), size, size)
|
||||||
} else if t.T == ArrayTy {
|
case ArrayTy:
|
||||||
// declare our array
|
// declare our array
|
||||||
refSlice = reflect.New(t.GetType()).Elem()
|
refSlice = reflect.New(t.GetType()).Elem()
|
||||||
} else {
|
default:
|
||||||
return nil, errors.New("abi: invalid type in array/slice unpacking stage")
|
return nil, errors.New("abi: invalid type in array/slice unpacking stage")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package keystore
|
package keystore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
|
|
@ -82,7 +83,9 @@ func (w *watcher) loop() {
|
||||||
defer watcher.Close()
|
defer watcher.Close()
|
||||||
|
|
||||||
if err := watcher.Add(w.ac.keydir); err != nil {
|
if err := watcher.Add(w.ac.keydir); err != nil {
|
||||||
logger.Warn("Failed to watch keystore folder", "err", err)
|
if !os.IsNotExist(err) {
|
||||||
|
logger.Warn("Failed to watch keystore folder", "err", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
## Preparing the smartcard
|
## Preparing the smartcard
|
||||||
|
|
||||||
**WARNING: FOILLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
|
**WARNING: FOLLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
|
||||||
|
|
||||||
You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap)
|
You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,4 +54,4 @@ for:
|
||||||
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||||
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||||
test_script:
|
test_script:
|
||||||
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC%
|
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ var (
|
||||||
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
|
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
|
||||||
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
|
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
|
||||||
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
|
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
|
||||||
|
UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
|
||||||
|
|
||||||
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
||||||
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
|
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc PayloadAttributes
|
var enc PayloadAttributes
|
||||||
|
|
@ -27,7 +28,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
enc.Random = p.Random
|
enc.Random = p.Random
|
||||||
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
||||||
enc.Withdrawals = p.Withdrawals
|
enc.Withdrawals = p.Withdrawals
|
||||||
|
enc.BeaconRoot = p.BeaconRoot
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,6 +39,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec PayloadAttributes
|
var dec PayloadAttributes
|
||||||
|
|
@ -65,6 +67,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
if dec.Withdrawals != nil {
|
if dec.Withdrawals != nil {
|
||||||
p.Withdrawals = dec.Withdrawals
|
p.Withdrawals = dec.Withdrawals
|
||||||
}
|
}
|
||||||
|
if dec.BeaconRoot != nil {
|
||||||
|
p.BeaconRoot = dec.BeaconRoot
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,14 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
|
||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc ExecutionPayloadEnvelope
|
var enc ExecutionPayloadEnvelope
|
||||||
enc.ExecutionPayload = e.ExecutionPayload
|
enc.ExecutionPayload = e.ExecutionPayload
|
||||||
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
||||||
enc.BlobsBundle = e.BlobsBundle
|
enc.BlobsBundle = e.BlobsBundle
|
||||||
|
enc.Override = e.Override
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +35,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
|
Override *bool `json:"shouldOverrideBuilder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec ExecutionPayloadEnvelope
|
var dec ExecutionPayloadEnvelope
|
||||||
|
|
@ -54,5 +57,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
||||||
if dec.BlobsBundle != nil {
|
if dec.BlobsBundle != nil {
|
||||||
e.BlobsBundle = dec.BlobsBundle
|
e.BlobsBundle = dec.BlobsBundle
|
||||||
}
|
}
|
||||||
|
if dec.Override != nil {
|
||||||
|
e.Override = *dec.Override
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,6 +35,7 @@ type PayloadAttributes struct {
|
||||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON type overrides for PayloadAttributes.
|
// JSON type overrides for PayloadAttributes.
|
||||||
|
|
@ -86,6 +86,7 @@ type ExecutionPayloadEnvelope struct {
|
||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobsBundleV1 struct {
|
type BlobsBundleV1 struct {
|
||||||
|
|
@ -177,7 +178,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||||
// and that the blockhash of the constructed block matches the parameters. Nil
|
// and that the blockhash of the constructed block matches the parameters. Nil
|
||||||
// Withdrawals value will propagate through the returned block. Empty
|
// Withdrawals value will propagate through the returned block. Empty
|
||||||
// Withdrawals value must be passed via non-nil, length 0 value in params.
|
// Withdrawals value must be passed via non-nil, length 0 value in params.
|
||||||
func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash) (*types.Block, error) {
|
func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
||||||
txs, err := decodeTransactions(params.Transactions)
|
txs, err := decodeTransactions(params.Transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -217,24 +218,25 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: params.ParentHash,
|
ParentHash: params.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
Coinbase: params.FeeRecipient,
|
Coinbase: params.FeeRecipient,
|
||||||
Root: params.StateRoot,
|
Root: params.StateRoot,
|
||||||
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
|
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
|
||||||
ReceiptHash: params.ReceiptsRoot,
|
ReceiptHash: params.ReceiptsRoot,
|
||||||
Bloom: types.BytesToBloom(params.LogsBloom),
|
Bloom: types.BytesToBloom(params.LogsBloom),
|
||||||
Difficulty: common.Big0,
|
Difficulty: common.Big0,
|
||||||
Number: new(big.Int).SetUint64(params.Number),
|
Number: new(big.Int).SetUint64(params.Number),
|
||||||
GasLimit: params.GasLimit,
|
GasLimit: params.GasLimit,
|
||||||
GasUsed: params.GasUsed,
|
GasUsed: params.GasUsed,
|
||||||
Time: params.Timestamp,
|
Time: params.Timestamp,
|
||||||
BaseFee: params.BaseFeePerGas,
|
BaseFee: params.BaseFeePerGas,
|
||||||
Extra: params.ExtraData,
|
Extra: params.ExtraData,
|
||||||
MixDigest: params.Random,
|
MixDigest: params.Random,
|
||||||
WithdrawalsHash: withdrawalsRoot,
|
WithdrawalsHash: withdrawalsRoot,
|
||||||
ExcessBlobGas: params.ExcessBlobGas,
|
ExcessBlobGas: params.ExcessBlobGas,
|
||||||
BlobGasUsed: params.BlobGasUsed,
|
BlobGasUsed: params.BlobGasUsed,
|
||||||
|
ParentBeaconRoot: beaconRoot,
|
||||||
}
|
}
|
||||||
|
|
||||||
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
|
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
|
||||||
|
|
@ -247,7 +249,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
|
||||||
|
|
||||||
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
||||||
// fields from the given block. It assumes the given block is post-merge block.
|
// fields from the given block. It assumes the given block is post-merge block.
|
||||||
func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *ExecutionPayloadEnvelope {
|
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
|
||||||
data := &ExecutableData{
|
data := &ExecutableData{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
ParentHash: block.ParentHash(),
|
ParentHash: block.ParentHash(),
|
||||||
|
|
@ -267,17 +269,19 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Bl
|
||||||
BlobGasUsed: block.BlobGasUsed(),
|
BlobGasUsed: block.BlobGasUsed(),
|
||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
}
|
}
|
||||||
blobsBundle := BlobsBundleV1{
|
bundle := BlobsBundleV1{
|
||||||
Commitments: make([]hexutil.Bytes, 0),
|
Commitments: make([]hexutil.Bytes, 0),
|
||||||
Blobs: make([]hexutil.Bytes, 0),
|
Blobs: make([]hexutil.Bytes, 0),
|
||||||
Proofs: make([]hexutil.Bytes, 0),
|
Proofs: make([]hexutil.Bytes, 0),
|
||||||
}
|
}
|
||||||
for i := range blobs {
|
for _, sidecar := range sidecars {
|
||||||
blobsBundle.Blobs = append(blobsBundle.Blobs, hexutil.Bytes(blobs[i][:]))
|
for j := range sidecar.Blobs {
|
||||||
blobsBundle.Commitments = append(blobsBundle.Commitments, hexutil.Bytes(commitments[i][:]))
|
bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
|
||||||
blobsBundle.Proofs = append(blobsBundle.Proofs, hexutil.Bytes(proofs[i][:]))
|
bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:]))
|
||||||
|
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &blobsBundle}
|
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
|
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,64 @@
|
||||||
# This file contains sha256 checksums of optional build dependencies.
|
# This file contains sha256 checksums of optional build dependencies.
|
||||||
|
|
||||||
2c5ee9c9ec1e733b0dbbc2bdfed3f62306e51d8172bf38f4f4e542b27520f597 go1.20.7.src.tar.gz
|
# version:spec-tests 1.0.6
|
||||||
785170eab380a8985d53896808b0a71336d0ea60e0a26099b4ccec77798b1cf4 go1.20.7.darwin-amd64.tar.gz
|
# https://github.com/ethereum/execution-spec-tests/releases
|
||||||
eea1e7e4c2f75c72629050e6a6c7c46c446d64056732a7787fb3ba16ace1982e go1.20.7.darwin-arm64.tar.gz
|
# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.6/
|
||||||
d8cff0357ac24eb06f3f280535397eeaacf95611d29f9b2abc3060f3d6dce3b4 go1.20.7.freebsd-386.tar.gz
|
485af7b66cf41eb3a8c1bd46632913b8eb95995df867cf665617bbc9b4beedd1 fixtures_develop.tar.gz
|
||||||
26918dcebf474a9e81ccf9f648cdf36968dfb76b481518cf615d78455dda4416 go1.20.7.freebsd-amd64.tar.gz
|
|
||||||
ddb48145f05bda2f4617a22c979d4e94b22802cdb1a1fde1b1974e733b26f091 go1.20.7.linux-386.tar.gz
|
|
||||||
f0a87f1bcae91c4b69f8dc2bc6d7e6bfcd7524fceec130af525058c0c17b1b44 go1.20.7.linux-amd64.tar.gz
|
|
||||||
44781ae3b153c3b07651d93b6bc554e835a36e2d72a696281c1e4dad9efffe43 go1.20.7.linux-arm64.tar.gz
|
|
||||||
7cc231b415b94f2f7065870a73f67dd2b0ec12b5a98052b7ee0121c42bc04f8d go1.20.7.linux-armv6l.tar.gz
|
|
||||||
6318a1db307c12b8afe68808bd6fae4fba1e558a85b958216096869ed506dcb3 go1.20.7.linux-ppc64le.tar.gz
|
|
||||||
26aea2ede8722ceecbd9db883328a8d963136fd96c11dacc356c44c4c19c6515 go1.20.7.linux-s390x.tar.gz
|
|
||||||
5b0ef6f58d3e04d6cc003aa98e9172f41ba9e091b1c98e7339b41c4c87fb78a1 go1.20.7.windows-386.zip
|
|
||||||
736dc6c7fcab1c96b682c8c93e38d7e371e62a17d34cb2c37d451a1147f66af9 go1.20.7.windows-amd64.zip
|
|
||||||
fc6f79c1e1ed9e506c65f2112ac4e387479916f1accb0d046a6a19ff6938baa5 go1.20.7.windows-arm64.zip
|
|
||||||
|
|
||||||
03c181fc1bb29ea3e73cbb23399c43b081063833a7cf7554b94e5a98308df53e golangci-lint-1.45.2-linux-riscv64.deb
|
# version:golang 1.21.4
|
||||||
08a50bbbf451ede6d5354179eb3e14a5634e156dfa92cb9a2606f855a637e35b golangci-lint-1.45.2-linux-ppc64le.rpm
|
# https://go.dev/dl/
|
||||||
0d12f6ec1296b5a70e392aa88cd2295cceef266165eb7028e675f455515dd1c9 golangci-lint-1.45.2-linux-armv7.deb
|
47b26a83d2b65a3c1c1bcace273b69bee49a7a7b5168a7604ded3d26a37bd787 go1.21.4.src.tar.gz
|
||||||
10f2846e2e50e4ea8ae426ee62dcd2227b23adddd8e991aa3c065927ac948735 golangci-lint-1.45.2-linux-ppc64le.deb
|
cd3bdcc802b759b70e8418bc7afbc4a65ca73a3fe576060af9fc8a2a5e71c3b8 go1.21.4.darwin-amd64.tar.gz
|
||||||
1463049b744871168095e3e8f687247d6040eeb895955b869889ea151e0603ab golangci-lint-1.45.2-linux-arm64.tar.gz
|
8b7caf2ac60bdff457dba7d4ff2a01def889592b834453431ae3caecf884f6a5 go1.21.4.darwin-arm64.tar.gz
|
||||||
15720f9c4c6f9324af695f081dc189adc7751b255759e78d7b2df1d7e9192533 golangci-lint-1.45.2-linux-amd64.deb
|
f1e685d086eb36f4be5b8b953b52baf7752bc6235400d84bb7d87e500b65f03e go1.21.4.freebsd-386.tar.gz
|
||||||
166d922e4d3cfe3d47786c590154a9c8ea689dff0aa92b73d2f5fc74fc570c29 golangci-lint-1.45.2-linux-arm64.rpm
|
59f9b32187efb98d344a3818a631d3815ebb5c7bbefc367bab6515caaca544e9 go1.21.4.freebsd-amd64.tar.gz
|
||||||
1a3754c69f7cc19ab89cbdcc2550da4cf9abb3120383c6b3bd440c1ec22da2e6 golangci-lint-1.45.2-freebsd-386.tar.gz
|
64d3e5d295806e137c9e39d1e1f10b00a30fcd5c2f230d72b3298f579bb3c89a go1.21.4.linux-386.tar.gz
|
||||||
1dec0aa46d4f0d241863b573f70129bdf1de9c595cf51172a840a588a4cd9fc5 golangci-lint-1.45.2-windows-amd64.zip
|
73cac0215254d0c7d1241fa40837851f3b9a8a742d0b54714cbdfb3feaf8f0af go1.21.4.linux-amd64.tar.gz
|
||||||
3198453806517c1ad988229f5e758ef850e671203f46d6905509df5bdf4dc24b golangci-lint-1.45.2-freebsd-armv7.tar.gz
|
ce1983a7289856c3a918e1fd26d41e072cc39f928adfb11ba1896440849b95da go1.21.4.linux-arm64.tar.gz
|
||||||
46a3cd1749d7b98adc2dc01510ddbe21abe42689c8a53fb0e81662713629f215 golangci-lint-1.45.2-linux-386.deb
|
6c62e89113750cc77c498194d13a03fadfda22bd2c7d44e8a826fd354db60252 go1.21.4.linux-armv6l.tar.gz
|
||||||
4e28bfb593d464b9e160f2acd5b71993836a183270bf8299b78ad31f7a168c0d golangci-lint-1.45.2-linux-arm64.deb
|
2c63b36d2adcfb22013102a2ee730f058ec2f93b9f27479793c80b2e3641783f go1.21.4.linux-ppc64le.tar.gz
|
||||||
5157a58c8f9ab85c33af2e46f0d7c57a3b1e8953b81d61130e292e09f545cfab golangci-lint-1.45.2-linux-mips64le.tar.gz
|
7a75ba4afc7a96058ca65903d994cd862381825d7dca12b2183f087c757c26c0 go1.21.4.linux-s390x.tar.gz
|
||||||
518cd027644129fbf8ec4f02bd6f9ad7278aae826f92b63c80d4d0819ddde49a golangci-lint-1.45.2-linux-armv6.rpm
|
870a0e462b94671dc2d6cac707e9e19f7524fdc3c90711e6cd4450c3713a8ce0 go1.21.4.windows-386.zip
|
||||||
595ad6c6dade4c064351bc309f411703e457f8ffbb7a1806b3d8ee713333427f golangci-lint-1.45.2-linux-amd64.tar.gz
|
79e5428e068c912d9cfa6cd115c13549856ec689c1332eac17f5d6122e19d595 go1.21.4.windows-amd64.zip
|
||||||
6994d6c80f0730751090986184a3481b4be2e6b6e84416238a2b857910045a4f golangci-lint-1.45.2-windows-arm64.zip
|
58bc7c6f4d4c72da2df4d2650c8222fe03c9978070eb3c66be8bbaa2a4757ac1 go1.21.4.windows-arm64.zip
|
||||||
6c81652fc340118811b487f713c441fc6f527800bf5fd11b8929d08124efa015 golangci-lint-1.45.2-linux-armv7.tar.gz
|
|
||||||
726cb045559b7518bafdd3459de70a0647c087eb1b4634627a4b2e95b1258580 golangci-lint-1.45.2-freebsd-amd64.tar.gz
|
# version:golangci 1.51.1
|
||||||
77df3774cdfda49b956d4a0e676da9a9b883f496ee37293c530770fef6b1d24e golangci-lint-1.45.2-linux-mips64.deb
|
# https://github.com/golangci/golangci-lint/releases/
|
||||||
7a9840f279a7d5d405bb434e101c2290964b3729630ac2add29280b962b7b9a5 golangci-lint-1.45.2-windows-armv6.zip
|
# https://github.com/golangci/golangci-lint/releases/download/v1.51.1/
|
||||||
7d4bf9a5d80ec467aaaf66e78dbdcab567bbc6ba8151334c714eee58766aae32 golangci-lint-1.45.2-windows-armv7.zip
|
fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz
|
||||||
7e5f8821d39bb11d273b0841b34355f56bd5a45a2d5179f0d09e614e0efc0482 golangci-lint-1.45.2-linux-s390x.rpm
|
75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz
|
||||||
828de1bde796b23d8656b17a8885fbd879ef612795d62d1e4618126b419728b5 golangci-lint-1.45.2-linux-mips64.rpm
|
e06b3459aaed356e1667580be00b05f41f3b2e29685d12cdee571c23e1edb414 golangci-lint-1.51.1-freebsd-386.tar.gz
|
||||||
879a52107a797678a03c175cc7cf441411a14a01f66dc87f70bdfa304a4129a6 golangci-lint-1.45.2-windows-386.zip
|
623ce2d0fa4d35cc2e8d69fa7334227ab592380962a13b4d9cdc77cf41db2008 golangci-lint-1.51.1-freebsd-amd64.tar.gz
|
||||||
87b6c7e3a3769f7d9abeb3bb82119b3c91e3c975300f6834fdeef8b2e37c98ff golangci-lint-1.45.2-linux-amd64.rpm
|
131365feb0584cc2736c43192fa673ca50e5b6b765456990cb379ecfb787e568 golangci-lint-1.51.1-freebsd-armv6.tar.gz
|
||||||
8b605c6d686c8af53ecc4ef39544541eeb1644d34cc10f9ffc5087808210c4ff golangci-lint-1.45.2-linux-s390x.deb
|
98fb627927cbb654f5bf85dcffc5f646666b2ce96ea0fed977c9fb28abd51532 golangci-lint-1.51.1-freebsd-armv7.tar.gz
|
||||||
9427dbf51d0ac6f73a0f992838bd40c817470cc5bf6c8e2e2bea6fac46d7af6e golangci-lint-1.45.2-linux-ppc64le.tar.gz
|
b36a99702fa762c15840261bc0fb41b4b1b16b8b19b8c0941bae98c85bb0f8b8 golangci-lint-1.51.1-linux-386.tar.gz
|
||||||
995e509e895ca6a64ffc7395ac884d5961bdec98423cb896b17f345a9b4a19cf golangci-lint-1.45.2-darwin-amd64.tar.gz
|
17aeb26c76820c22efa0e1838b0ab93e90cfedef43fbfc9a2f33f27eb9e5e070 golangci-lint-1.51.1-linux-amd64.tar.gz
|
||||||
a3f36278f2ea5516341e9071a2df6e65df272be80230b5406a12b72c6d425bee golangci-lint-1.45.2-linux-armv7.rpm
|
9744bc34e7b8d82ca788b667bfb7155a39b4be9aef43bf9f10318b1372cea338 golangci-lint-1.51.1-linux-arm64.tar.gz
|
||||||
a5e12c50c23e87ac1deffc872f92ae85427b1198604969399805ae47cfe43f08 golangci-lint-1.45.2-linux-riscv64.tar.gz
|
0dda8dbeb2ff7455a044ec8e347f2fc6d655d2e99d281b3b95e88167031c673d golangci-lint-1.51.1-linux-armv6.tar.gz
|
||||||
aa8fa1be0729dbc2fbc4e01e82027097613eee74bd686ebef20f860b01fff8b3 golangci-lint-1.45.2-freebsd-armv6.tar.gz
|
0512f311b11d43b8b22989d929f0fe8a2e1e5ebe497f1eb0ff73a0fc3d188fd1 golangci-lint-1.51.1-linux-armv7.tar.gz
|
||||||
c2b9669decc1b638cf2ee9060571af4e255f6dfcbb225c293e3a7ee4bb2c7217 golangci-lint-1.45.2-darwin-arm64.tar.gz
|
d767108dcf84a8eaa844df3454cb0f75a492f4e7102ecc2b0a3545cfe073a566 golangci-lint-1.51.1-linux-loong64.tar.gz
|
||||||
dfa8bdaf0387aec1cd5c1aa8857f67b2bbdfc2e42efce540c8fb9bbe3e8af302 golangci-lint-1.45.2-linux-armv6.tar.gz
|
3bd56c54daec16585b2668e0dfabb27af2c2b38cc0fdb46923e2521e1634846b golangci-lint-1.51.1-linux-mips64.tar.gz
|
||||||
eb8b8539dd017eee5c131ea9b875893ab2cebeeca41e8c6624907fb02224d643 golangci-lint-1.45.2-linux-386.rpm
|
f72f5adfa2219e15d2414c9a2966f86e74556cf17a85c727a7fb7770a16cf814 golangci-lint-1.51.1-linux-mips64le.tar.gz
|
||||||
ed6c7e17a857f30d715c5302fa250d95936936b277024bffea201187a257d7a7 golangci-lint-1.45.2-linux-armv6.deb
|
e605521dac98096d8737e1997c954f41f1d0d8275b8731f62783d410c23574b9 golangci-lint-1.51.1-linux-ppc64le.tar.gz
|
||||||
ef4d0154ace4001f01b288baeb118176242efb4fd163e178763e3213b77ef30b golangci-lint-1.45.2-linux-mips64le.deb
|
2f683217b814339e74d61ca700922d8407f15addd6d4c5e8b156fbab79f26a87 golangci-lint-1.51.1-linux-riscv64.tar.gz
|
||||||
ef7002a2229f5ff5ba201a715fcf877664ea88decbe58e69d163293913024955 golangci-lint-1.45.2-linux-s390x.tar.gz
|
d98528292b65971a3594e5880530e7624597dc9806fcfccdfbe39be411713d63 golangci-lint-1.51.1-linux-s390x.tar.gz
|
||||||
f13ecbd09228632e6bbe91a8324bd675c406eed22eb6d2c1e8192eed9ec4f914 golangci-lint-1.45.2-linux-386.tar.gz
|
9bb2d0fe9e692ed0aea4f2537e3e6862b2f6768fe2849a84f4a6ad09da9fd971 golangci-lint-1.51.1-netbsd-386.tar.gz
|
||||||
f4cd9cfb09252f51699407277512263cae8409b665dd764f55a34738d0e89edc golangci-lint-1.45.2-linux-riscv64.rpm
|
34cafdcd11ae73ae88d66c33eb8449f5c976fc3e37b44774dbe9c71caa95e592 golangci-lint-1.51.1-netbsd-amd64.tar.gz
|
||||||
fb1945dc59d37c9d14bf0a4aea11ea8651fa0e1d582ea80c4c44d0a536c08893 golangci-lint-1.45.2-linux-mips64.tar.gz
|
f8b4e1e47ac17caafe8a5f32f975a2b6a7cb14c27c0f73c1fb15c20ca91c2e03 golangci-lint-1.51.1-netbsd-armv6.tar.gz
|
||||||
fe542c22738010f453c735a3c410decfd3784d1bd394b395c298ee298fc4c606 golangci-lint-1.45.2-linux-mips64le.rpm
|
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
|
||||||
|
|
||||||
|
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
||||||
|
#
|
||||||
|
# This version is fine to be old and full of security holes, we just use it
|
||||||
|
# to build the latest Go. Don't change it. If it ever becomes insufficient,
|
||||||
|
# we need to switch over to a recursive builder to jump across supported
|
||||||
|
# versions.
|
||||||
|
#
|
||||||
|
# version:ppa-builder 1.19.6
|
||||||
|
# https://go.dev/dl/
|
||||||
|
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
|
||||||
|
|
|
||||||
100
build/ci.go
100
build/ci.go
|
|
@ -120,15 +120,15 @@ var (
|
||||||
// Distros for which packages are created.
|
// Distros for which packages are created.
|
||||||
// Note: vivid is unsupported because there is no golang-1.6 package for it.
|
// 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:
|
// Note: the following Ubuntu releases have been officially deprecated on Launchpad:
|
||||||
// wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish
|
// wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish,
|
||||||
|
// kinetic
|
||||||
debDistroGoBoots = map[string]string{
|
debDistroGoBoots = map[string]string{
|
||||||
"trusty": "golang-1.11", // EOL: 04/2024
|
"trusty": "golang-1.11", // EOL: 04/2024
|
||||||
"xenial": "golang-go", // EOL: 04/2026
|
"xenial": "golang-go", // EOL: 04/2026
|
||||||
"bionic": "golang-go", // EOL: 04/2028
|
"bionic": "golang-go", // EOL: 04/2028
|
||||||
"focal": "golang-go", // EOL: 04/2030
|
"focal": "golang-go", // EOL: 04/2030
|
||||||
"jammy": "golang-go", // EOL: 04/2032
|
"jammy": "golang-go", // EOL: 04/2032
|
||||||
"kinetic": "golang-go", // EOL: 07/2023
|
"lunar": "golang-go", // EOL: 01/2024
|
||||||
"lunar": "golang-go", // EOL: 01/2024
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debGoBootPaths = map[string]string{
|
debGoBootPaths = map[string]string{
|
||||||
|
|
@ -136,18 +136,8 @@ var (
|
||||||
"golang-go": "/usr/lib/go",
|
"golang-go": "/usr/lib/go",
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the version of Go that will be downloaded by
|
// This is where the tests should be unpacked.
|
||||||
//
|
executionSpecTestsDir = "tests/spec-tests"
|
||||||
// go run ci.go install -dlgo
|
|
||||||
dlgoVersion = "1.20.7"
|
|
||||||
|
|
||||||
// This is the version of Go that will be used to bootstrap the PPA builder.
|
|
||||||
//
|
|
||||||
// This version is fine to be old and full of security holes, we just use it
|
|
||||||
// to build the latest Go. Don't change it. If it ever becomes insufficient,
|
|
||||||
// we need to switch over to a recursive builder to jumpt across supported
|
|
||||||
// versions.
|
|
||||||
gobootVersion = "1.19.6"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
|
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
|
||||||
|
|
@ -185,6 +175,8 @@ func main() {
|
||||||
doWindowsInstaller(os.Args[2:])
|
doWindowsInstaller(os.Args[2:])
|
||||||
case "purge":
|
case "purge":
|
||||||
doPurge(os.Args[2:])
|
doPurge(os.Args[2:])
|
||||||
|
case "sanitycheck":
|
||||||
|
doSanityCheck()
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown command ", os.Args[1])
|
log.Fatal("unknown command ", os.Args[1])
|
||||||
}
|
}
|
||||||
|
|
@ -206,9 +198,8 @@ func doInstall(cmdline []string) {
|
||||||
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
|
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
|
||||||
if *dlgo {
|
if *dlgo {
|
||||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
tc.Root = build.DownloadGo(csdb, dlgoVersion)
|
tc.Root = build.DownloadGo(csdb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable CLI markdown doc generation in release builds.
|
// Disable CLI markdown doc generation in release builds.
|
||||||
buildTags := []string{"urfave_cli_no_docs"}
|
buildTags := []string{"urfave_cli_no_docs"}
|
||||||
|
|
||||||
|
|
@ -294,14 +285,19 @@ func doTest(cmdline []string) {
|
||||||
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
|
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
|
||||||
verbose = flag.Bool("v", false, "Whether to log verbosely")
|
verbose = flag.Bool("v", false, "Whether to log verbosely")
|
||||||
race = flag.Bool("race", false, "Execute the race detector")
|
race = flag.Bool("race", false, "Execute the race detector")
|
||||||
|
short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
|
||||||
|
cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
||||||
|
// Get test fixtures.
|
||||||
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
downloadSpecTestFixtures(csdb, *cachedir)
|
||||||
|
|
||||||
// Configure the toolchain.
|
// Configure the toolchain.
|
||||||
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
|
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
|
||||||
if *dlgo {
|
if *dlgo {
|
||||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
tc.Root = build.DownloadGo(csdb)
|
||||||
tc.Root = build.DownloadGo(csdb, dlgoVersion)
|
|
||||||
}
|
}
|
||||||
gotest := tc.Go("test")
|
gotest := tc.Go("test")
|
||||||
|
|
||||||
|
|
@ -311,6 +307,9 @@ func doTest(cmdline []string) {
|
||||||
// Enable CKZG backend in CI.
|
// Enable CKZG backend in CI.
|
||||||
gotest.Args = append(gotest.Args, "-tags=ckzg")
|
gotest.Args = append(gotest.Args, "-tags=ckzg")
|
||||||
|
|
||||||
|
// Enable integration-tests
|
||||||
|
gotest.Args = append(gotest.Args, "-tags=integrationtests")
|
||||||
|
|
||||||
// Test a single package at a time. CI builders are slow
|
// Test a single package at a time. CI builders are slow
|
||||||
// and some tests run into timeouts under load.
|
// and some tests run into timeouts under load.
|
||||||
gotest.Args = append(gotest.Args, "-p", "1")
|
gotest.Args = append(gotest.Args, "-p", "1")
|
||||||
|
|
@ -323,6 +322,9 @@ func doTest(cmdline []string) {
|
||||||
if *race {
|
if *race {
|
||||||
gotest.Args = append(gotest.Args, "-race")
|
gotest.Args = append(gotest.Args, "-race")
|
||||||
}
|
}
|
||||||
|
if *short {
|
||||||
|
gotest.Args = append(gotest.Args, "-short")
|
||||||
|
}
|
||||||
|
|
||||||
packages := []string{"./..."}
|
packages := []string{"./..."}
|
||||||
if len(flag.CommandLine.Args()) > 0 {
|
if len(flag.CommandLine.Args()) > 0 {
|
||||||
|
|
@ -332,6 +334,25 @@ func doTest(cmdline []string) {
|
||||||
build.MustRun(gotest)
|
build.MustRun(gotest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
|
||||||
|
func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
|
||||||
|
executionSpecTestsVersion, err := build.Version(csdb, "spec-tests")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
ext := ".tar.gz"
|
||||||
|
base := "fixtures_develop" // TODO(MariusVanDerWijden) rename once the version becomes part of the filename
|
||||||
|
url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/v%s/%s%s", executionSpecTestsVersion, base, ext)
|
||||||
|
archivePath := filepath.Join(cachedir, base+ext)
|
||||||
|
if err := csdb.DownloadFile(url, archivePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return filepath.Join(cachedir, base)
|
||||||
|
}
|
||||||
|
|
||||||
// doLint runs golangci-lint on requested packages.
|
// doLint runs golangci-lint on requested packages.
|
||||||
func doLint(cmdline []string) {
|
func doLint(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
|
|
@ -351,9 +372,11 @@ func doLint(cmdline []string) {
|
||||||
|
|
||||||
// downloadLinter downloads and unpacks golangci-lint.
|
// downloadLinter downloads and unpacks golangci-lint.
|
||||||
func downloadLinter(cachedir string) string {
|
func downloadLinter(cachedir string) string {
|
||||||
const version = "1.45.2"
|
|
||||||
|
|
||||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
version, err := build.Version(csdb, "golangci")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
arch := runtime.GOARCH
|
arch := runtime.GOARCH
|
||||||
ext := ".tar.gz"
|
ext := ".tar.gz"
|
||||||
|
|
||||||
|
|
@ -729,9 +752,30 @@ func doDebianSource(cmdline []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// downloadGoBootstrapSources downloads the Go source tarball that will be used
|
||||||
|
// to bootstrap the builder Go.
|
||||||
|
func downloadGoBootstrapSources(cachedir string) string {
|
||||||
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
gobootVersion, err := build.Version(csdb, "ppa-builder")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion)
|
||||||
|
url := "https://dl.google.com/go/" + file
|
||||||
|
dst := filepath.Join(cachedir, file)
|
||||||
|
if err := csdb.DownloadFile(url, dst); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
// downloadGoSources downloads the Go source tarball.
|
// downloadGoSources downloads the Go source tarball.
|
||||||
func downloadGoSources(cachedir string) string {
|
func downloadGoSources(cachedir string) string {
|
||||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
dlgoVersion, err := build.Version(csdb, "golang")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion)
|
file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion)
|
||||||
url := "https://dl.google.com/go/" + file
|
url := "https://dl.google.com/go/" + file
|
||||||
dst := filepath.Join(cachedir, file)
|
dst := filepath.Join(cachedir, file)
|
||||||
|
|
@ -1058,3 +1102,7 @@ func doPurge(cmdline []string) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doSanityCheck() {
|
||||||
|
build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt"))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,10 +65,8 @@ var (
|
||||||
"vendor/", "tests/testdata/", "build/",
|
"vendor/", "tests/testdata/", "build/",
|
||||||
|
|
||||||
// don't relicense vendored sources
|
// don't relicense vendored sources
|
||||||
"cmd/internal/browser",
|
|
||||||
"common/bitutil/bitutil",
|
"common/bitutil/bitutil",
|
||||||
"common/prque/",
|
"common/prque/",
|
||||||
"consensus/ethash/xor.go",
|
|
||||||
"crypto/blake2b/",
|
"crypto/blake2b/",
|
||||||
"crypto/bn256/",
|
"crypto/bn256/",
|
||||||
"crypto/bls12381/",
|
"crypto/bls12381/",
|
||||||
|
|
@ -78,6 +76,7 @@ var (
|
||||||
"log/",
|
"log/",
|
||||||
"metrics/",
|
"metrics/",
|
||||||
"signer/rules/deps",
|
"signer/rules/deps",
|
||||||
|
"internal/reexec",
|
||||||
|
|
||||||
// skip special licenses
|
// skip special licenses
|
||||||
"crypto/secp256k1", // Relicensed to BSD-3 via https://github.com/ethereum/go-ethereum/pull/17225
|
"crypto/secp256k1", // Relicensed to BSD-3 via https://github.com/ethereum/go-ethereum/pull/17225
|
||||||
|
|
|
||||||
|
|
@ -1333,7 +1333,7 @@ func GenDoc(ctx *cli.Context) error {
|
||||||
URL: accounts.URL{Path: ".. ignored .."},
|
URL: accounts.URL{Path: ".. ignored .."},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"),
|
Address: common.MaxAddress,
|
||||||
},
|
},
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/reexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
const registeredName = "clef-test"
|
const registeredName = "clef-test"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ set to standard output. The following filters are supported:
|
||||||
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
|
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
|
||||||
- `-ip <CIDR>` filters nodes by IP subnet
|
- `-ip <CIDR>` filters nodes by IP subnet
|
||||||
- `-min-age <duration>` filters nodes by 'first seen' time
|
- `-min-age <duration>` filters nodes by 'first seen' time
|
||||||
- `-eth-network <mainnet/goerli/sepolia>` filters nodes by "eth" ENR entry
|
- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry
|
||||||
- `-les-server` filters nodes by LES server support
|
- `-les-server` filters nodes by LES server support
|
||||||
- `-snap` filters nodes by snap protocol support
|
- `-snap` filters nodes by snap protocol support
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -51,7 +52,14 @@ type resolver interface {
|
||||||
RequestENR(*enode.Node) (*enode.Node, error)
|
RequestENR(*enode.Node) (*enode.Node, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler {
|
func newCrawler(input nodeSet, bootnodes []*enode.Node, disc resolver, iters ...enode.Iterator) (*crawler, error) {
|
||||||
|
if len(input) == 0 {
|
||||||
|
input.add(bootnodes...)
|
||||||
|
}
|
||||||
|
if len(input) == 0 {
|
||||||
|
return nil, errors.New("no input nodes to start crawling")
|
||||||
|
}
|
||||||
|
|
||||||
c := &crawler{
|
c := &crawler{
|
||||||
input: input,
|
input: input,
|
||||||
output: make(nodeSet, len(input)),
|
output: make(nodeSet, len(input)),
|
||||||
|
|
@ -67,8 +75,7 @@ func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler
|
||||||
for id, n := range input {
|
for id, n := range input {
|
||||||
c.output[id] = n
|
c.output[id] = n
|
||||||
}
|
}
|
||||||
|
return c, nil
|
||||||
return c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocognit
|
// nolint:gocognit
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,7 @@ var discoveryNodeFlags = []cli.Flag{
|
||||||
|
|
||||||
func discv4Ping(ctx *cli.Context) error {
|
func discv4Ping(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
|
disc, _ := startV4(ctx)
|
||||||
disc := startV4(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
@ -161,8 +160,7 @@ func discv4Ping(ctx *cli.Context) error {
|
||||||
|
|
||||||
func discv4RequestRecord(ctx *cli.Context) error {
|
func discv4RequestRecord(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
|
disc, _ := startV4(ctx)
|
||||||
disc := startV4(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
respN, err := disc.RequestENR(n)
|
respN, err := disc.RequestENR(n)
|
||||||
|
|
@ -177,8 +175,7 @@ func discv4RequestRecord(ctx *cli.Context) error {
|
||||||
|
|
||||||
func discv4Resolve(ctx *cli.Context) error {
|
func discv4Resolve(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
|
disc, _ := startV4(ctx)
|
||||||
disc := startV4(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
fmt.Println(disc.Resolve(n).String())
|
fmt.Println(disc.Resolve(n).String())
|
||||||
|
|
@ -210,10 +207,13 @@ func discv4ResolveJSON(ctx *cli.Context) error {
|
||||||
nodeargs = append(nodeargs, n)
|
nodeargs = append(nodeargs, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the crawler.
|
disc, config := startV4(ctx)
|
||||||
disc := startV4(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
c := newCrawler(inputSet, disc, enode.IterNodes(nodeargs))
|
|
||||||
|
c, err := newCrawler(inputSet, config.Bootnodes, disc, enode.IterNodes(nodeargs))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
c.revalidateInterval = 0
|
c.revalidateInterval = 0
|
||||||
output := c.run(0, 1)
|
output := c.run(0, 1)
|
||||||
writeNodesJSON(nodesFile, output)
|
writeNodesJSON(nodesFile, output)
|
||||||
|
|
@ -227,16 +227,18 @@ func discv4Crawl(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
nodesFile := ctx.Args().First()
|
nodesFile := ctx.Args().First()
|
||||||
|
inputSet := make(nodeSet)
|
||||||
var inputSet nodeSet
|
|
||||||
|
|
||||||
if common.FileExist(nodesFile) {
|
if common.FileExist(nodesFile) {
|
||||||
inputSet = loadNodesJSON(nodesFile)
|
inputSet = loadNodesJSON(nodesFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
disc := startV4(ctx)
|
disc, config := startV4(ctx)
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
c := newCrawler(inputSet, disc, disc.RandomNodes())
|
|
||||||
|
c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
c.revalidateInterval = 10 * time.Minute
|
c.revalidateInterval = 10 * time.Minute
|
||||||
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
|
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
|
||||||
writeNodesJSON(nodesFile, output)
|
writeNodesJSON(nodesFile, output)
|
||||||
|
|
@ -259,7 +261,7 @@ func discv4Test(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// startV4 starts an ephemeral discovery V4 node.
|
// startV4 starts an ephemeral discovery V4 node.
|
||||||
func startV4(ctx *cli.Context) *discover.UDPv4 {
|
func startV4(ctx *cli.Context) (*discover.UDPv4, discover.Config) {
|
||||||
ln, config := makeDiscoveryConfig(ctx)
|
ln, config := makeDiscoveryConfig(ctx)
|
||||||
socket := listen(ctx, ln)
|
socket := listen(ctx, ln)
|
||||||
|
|
||||||
|
|
@ -267,8 +269,7 @@ func startV4(ctx *cli.Context) *discover.UDPv4 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
return disc, config
|
||||||
return disc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
|
func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,7 @@ var (
|
||||||
|
|
||||||
func discv5Ping(ctx *cli.Context) error {
|
func discv5Ping(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
|
disc, _ := startV5(ctx)
|
||||||
disc := startV5(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
fmt.Println(disc.Ping(n))
|
fmt.Println(disc.Ping(n))
|
||||||
|
|
@ -93,8 +92,7 @@ func discv5Ping(ctx *cli.Context) error {
|
||||||
|
|
||||||
func discv5Resolve(ctx *cli.Context) error {
|
func discv5Resolve(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
|
disc, _ := startV5(ctx)
|
||||||
disc := startV5(ctx)
|
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
fmt.Println(disc.Resolve(n))
|
fmt.Println(disc.Resolve(n))
|
||||||
|
|
@ -108,16 +106,18 @@ func discv5Crawl(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
nodesFile := ctx.Args().First()
|
nodesFile := ctx.Args().First()
|
||||||
|
inputSet := make(nodeSet)
|
||||||
var inputSet nodeSet
|
|
||||||
|
|
||||||
if common.FileExist(nodesFile) {
|
if common.FileExist(nodesFile) {
|
||||||
inputSet = loadNodesJSON(nodesFile)
|
inputSet = loadNodesJSON(nodesFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
disc := startV5(ctx)
|
disc, config := startV5(ctx)
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
c := newCrawler(inputSet, disc, disc.RandomNodes())
|
|
||||||
|
c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
c.revalidateInterval = 10 * time.Minute
|
c.revalidateInterval = 10 * time.Minute
|
||||||
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
|
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
|
||||||
writeNodesJSON(nodesFile, output)
|
writeNodesJSON(nodesFile, output)
|
||||||
|
|
@ -137,7 +137,7 @@ func discv5Test(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func discv5Listen(ctx *cli.Context) error {
|
func discv5Listen(ctx *cli.Context) error {
|
||||||
disc := startV5(ctx)
|
disc, _ := startV5(ctx)
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
fmt.Println(disc.Self())
|
fmt.Println(disc.Self())
|
||||||
|
|
@ -145,7 +145,7 @@ func discv5Listen(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// startV5 starts an ephemeral discovery v5 node.
|
// startV5 starts an ephemeral discovery v5 node.
|
||||||
func startV5(ctx *cli.Context) *discover.UDPv5 {
|
func startV5(ctx *cli.Context) (*discover.UDPv5, discover.Config) {
|
||||||
ln, config := makeDiscoveryConfig(ctx)
|
ln, config := makeDiscoveryConfig(ctx)
|
||||||
socket := listen(ctx, ln)
|
socket := listen(ctx, ln)
|
||||||
|
|
||||||
|
|
@ -153,6 +153,5 @@ func startV5(ctx *cli.Context) *discover.UDPv5 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
return disc, config
|
||||||
return disc
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
|
||||||
records = lrecords
|
records = lrecords
|
||||||
|
|
||||||
log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name))
|
log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name))
|
||||||
|
entries, _, err := c.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), cloudflare.ListDNSRecordsParams{Type: "TXT"})
|
||||||
entries, err := c.DNSRecords(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT"})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -163,16 +162,26 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
|
||||||
if path != name {
|
if path != name {
|
||||||
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
|
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
|
||||||
}
|
}
|
||||||
|
record := cloudflare.CreateDNSRecordParams{Type: "TXT", Name: path, Content: val, TTL: ttl}
|
||||||
record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
|
_, err = c.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
|
||||||
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
|
|
||||||
} else if old.Content != val {
|
} else if old.Content != val {
|
||||||
// Entry already exists, only change its content.
|
// Entry already exists, only change its content.
|
||||||
log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val))
|
log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val))
|
||||||
|
|
||||||
updated++
|
updated++
|
||||||
old.Content = val
|
|
||||||
err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old)
|
record := cloudflare.UpdateDNSRecordParams{
|
||||||
|
Type: old.Type,
|
||||||
|
Name: old.Name,
|
||||||
|
Content: val,
|
||||||
|
Data: old.Data,
|
||||||
|
ID: old.ID,
|
||||||
|
Priority: old.Priority,
|
||||||
|
TTL: old.TTL,
|
||||||
|
Proxied: old.Proxied,
|
||||||
|
Tags: old.Tags,
|
||||||
|
}
|
||||||
|
_, err = c.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
|
||||||
} else {
|
} else {
|
||||||
skipped++
|
skipped++
|
||||||
|
|
||||||
|
|
@ -198,8 +207,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
|
||||||
log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content))
|
log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content))
|
||||||
|
|
||||||
deleted++
|
deleted++
|
||||||
|
if err := c.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), entry.ID); err != nil {
|
||||||
if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil {
|
|
||||||
return fmt.Errorf("failed to delete %s: %v", path, err)
|
return fmt.Errorf("failed to delete %s: %v", path, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ func (c *Chain) RootAt(height int) common.Hash {
|
||||||
|
|
||||||
// ForkID gets the fork id of the chain.
|
// ForkID gets the fork id of the chain.
|
||||||
func (c *Chain) ForkID() forkid.ID {
|
func (c *Chain) ForkID() forkid.ID {
|
||||||
return forkid.NewID(c.chainConfig, c.blocks[0].Hash(), uint64(c.Len()), c.blocks[0].Time())
|
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
|
// Shorten returns a copy chain of a desired height from the imported
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ func TestChain_GetHeaders(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
req: GetBlockHeaders{
|
req: GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Number: uint64(2)},
|
Origin: eth.HashOrNumber{Number: uint64(2)},
|
||||||
Amount: uint64(5),
|
Amount: uint64(5),
|
||||||
Skip: 1,
|
Skip: 1,
|
||||||
|
|
@ -163,7 +163,7 @@ func TestChain_GetHeaders(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
req: GetBlockHeaders{
|
req: GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
|
Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
|
||||||
Amount: uint64(3),
|
Amount: uint64(3),
|
||||||
Skip: 0,
|
Skip: 0,
|
||||||
|
|
@ -178,7 +178,7 @@ func TestChain_GetHeaders(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
req: GetBlockHeaders{
|
req: GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
|
Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
|
||||||
Amount: uint64(1),
|
Amount: uint64(1),
|
||||||
Skip: 0,
|
Skip: 0,
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ func (s *Suite) dial() (*Conn, error) {
|
||||||
}
|
}
|
||||||
// set default p2p capabilities
|
// set default p2p capabilities
|
||||||
conn.caps = []p2p.Cap{
|
conn.caps = []p2p.Cap{
|
||||||
{Name: "eth", Version: 66},
|
|
||||||
{Name: "eth", Version: 67},
|
{Name: "eth", Version: 67},
|
||||||
{Name: "eth", Version: 68},
|
{Name: "eth", Version: 68},
|
||||||
}
|
}
|
||||||
|
|
@ -259,8 +258,8 @@ func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &BlockHeaders{
|
resp := &BlockHeaders{
|
||||||
RequestId: msg.ReqID(),
|
RequestId: msg.ReqID(),
|
||||||
BlockHeadersPacket: eth.BlockHeadersPacket(headers),
|
BlockHeadersRequest: eth.BlockHeadersRequest(headers),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Write(resp); err != nil {
|
if err := c.Write(resp); err != nil {
|
||||||
|
|
@ -292,9 +291,7 @@ func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
|
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
|
||||||
}
|
}
|
||||||
|
headers := []*types.Header(resp.BlockHeadersRequest)
|
||||||
headers := []*types.Header(resp.BlockHeadersPacket)
|
|
||||||
|
|
||||||
return headers, nil
|
return headers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,7 +413,7 @@ func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block) error {
|
||||||
conn.SetReadDeadline(time.Now().Add(20 * time.Second))
|
conn.SetReadDeadline(time.Now().Add(20 * time.Second))
|
||||||
// create request
|
// create request
|
||||||
req := &GetBlockHeaders{
|
req := &GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Hash: block.Hash()},
|
Origin: eth.HashOrNumber{Hash: block.Hash()},
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
|
|
@ -663,8 +660,8 @@ func (s *Suite) hashAnnounce() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sendConn.Write(&BlockHeaders{
|
err = sendConn.Write(&BlockHeaders{
|
||||||
RequestId: blockHeaderReq.ReqID(),
|
RequestId: blockHeaderReq.ReqID(),
|
||||||
BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()},
|
BlockHeadersRequest: eth.BlockHeadersRequest{nextBlock.Header()},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
||||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ type accRangeTest struct {
|
||||||
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
||||||
var (
|
var (
|
||||||
root = s.chain.RootAt(999)
|
root = s.chain.RootAt(999)
|
||||||
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
ffHash = common.MaxHash
|
||||||
zero = common.Hash{}
|
zero = common.Hash{}
|
||||||
firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
|
firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
|
||||||
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
||||||
|
|
@ -128,7 +128,7 @@ type stRangesTest struct {
|
||||||
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
|
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
|
||||||
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
|
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
|
||||||
var (
|
var (
|
||||||
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
ffHash = common.MaxHash
|
||||||
zero = common.Hash{}
|
zero = common.Hash{}
|
||||||
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
|
||||||
secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
|
secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
|
||||||
|
|
@ -556,21 +556,13 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
|
||||||
for i, key := range hashes {
|
for i, key := range hashes {
|
||||||
keys[i] = common.CopyBytes(key[:])
|
keys[i] = common.CopyBytes(key[:])
|
||||||
}
|
}
|
||||||
|
nodes := make(trienode.ProofList, len(proof))
|
||||||
nodes := make(light.NodeList, len(proof))
|
|
||||||
for i, node := range proof {
|
for i, node := range proof {
|
||||||
nodes[i] = node
|
nodes[i] = node
|
||||||
}
|
}
|
||||||
|
proofdb := nodes.Set()
|
||||||
|
|
||||||
proofdb := nodes.NodeSet()
|
_, err = trie.VerifyRangeProof(tc.root, tc.origin[:], keys, accounts, proofdb)
|
||||||
|
|
||||||
var end []byte
|
|
||||||
if len(keys) > 0 {
|
|
||||||
end = keys[len(keys)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
|
||||||
}
|
}
|
||||||
// write request
|
// write request
|
||||||
req := &GetBlockHeaders{
|
req := &GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
|
Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
Skip: 1,
|
Skip: 1,
|
||||||
|
|
@ -160,7 +160,7 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
||||||
// create two requests
|
// create two requests
|
||||||
req1 := &GetBlockHeaders{
|
req1 := &GetBlockHeaders{
|
||||||
RequestId: uint64(111),
|
RequestId: uint64(111),
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
Hash: s.chain.blocks[1].Hash(),
|
Hash: s.chain.blocks[1].Hash(),
|
||||||
},
|
},
|
||||||
|
|
@ -171,7 +171,7 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
||||||
}
|
}
|
||||||
req2 := &GetBlockHeaders{
|
req2 := &GetBlockHeaders{
|
||||||
RequestId: uint64(222),
|
RequestId: uint64(222),
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
Hash: s.chain.blocks[1].Hash(),
|
Hash: s.chain.blocks[1].Hash(),
|
||||||
},
|
},
|
||||||
|
|
@ -215,12 +215,10 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get expected headers for request 2: %v", err)
|
t.Fatalf("failed to get expected headers for request 2: %v", err)
|
||||||
}
|
}
|
||||||
|
if !headersMatch(expected1, headers1.BlockHeadersRequest) {
|
||||||
if !headersMatch(expected1, headers1.BlockHeadersPacket) {
|
|
||||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
||||||
}
|
}
|
||||||
|
if !headersMatch(expected2, headers2.BlockHeadersRequest) {
|
||||||
if !headersMatch(expected2, headers2.BlockHeadersPacket) {
|
|
||||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +241,7 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
|
||||||
reqID := uint64(1234)
|
reqID := uint64(1234)
|
||||||
request1 := &GetBlockHeaders{
|
request1 := &GetBlockHeaders{
|
||||||
RequestId: reqID,
|
RequestId: reqID,
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
Number: 1,
|
Number: 1,
|
||||||
},
|
},
|
||||||
|
|
@ -252,7 +250,7 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
|
||||||
}
|
}
|
||||||
request2 := &GetBlockHeaders{
|
request2 := &GetBlockHeaders{
|
||||||
RequestId: reqID,
|
RequestId: reqID,
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
Number: 33,
|
Number: 33,
|
||||||
},
|
},
|
||||||
|
|
@ -294,12 +292,10 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get expected block headers: %v", err)
|
t.Fatalf("failed to get expected block headers: %v", err)
|
||||||
}
|
}
|
||||||
|
if !headersMatch(expected1, headers1.BlockHeadersRequest) {
|
||||||
if !headersMatch(expected1, headers1.BlockHeadersPacket) {
|
|
||||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
||||||
}
|
}
|
||||||
|
if !headersMatch(expected2, headers2.BlockHeadersRequest) {
|
||||||
if !headersMatch(expected2, headers2.BlockHeadersPacket) {
|
|
||||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +315,7 @@ func (s *Suite) TestZeroRequestID(t *utesting.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &GetBlockHeaders{
|
req := &GetBlockHeaders{
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
Origin: eth.HashOrNumber{Number: 0},
|
Origin: eth.HashOrNumber{Number: 0},
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
|
|
@ -356,7 +352,7 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
||||||
// create block bodies request
|
// create block bodies request
|
||||||
req := &GetBlockBodies{
|
req := &GetBlockBodies{
|
||||||
RequestId: uint64(55),
|
RequestId: uint64(55),
|
||||||
GetBlockBodiesPacket: eth.GetBlockBodiesPacket{
|
GetBlockBodiesRequest: eth.GetBlockBodiesRequest{
|
||||||
s.chain.blocks[54].Hash(),
|
s.chain.blocks[54].Hash(),
|
||||||
s.chain.blocks[75].Hash(),
|
s.chain.blocks[75].Hash(),
|
||||||
},
|
},
|
||||||
|
|
@ -371,13 +367,11 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
|
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
|
||||||
}
|
}
|
||||||
|
bodies := resp.BlockBodiesResponse
|
||||||
bodies := resp.BlockBodiesPacket
|
|
||||||
t.Logf("received %d block bodies", len(bodies))
|
t.Logf("received %d block bodies", len(bodies))
|
||||||
|
if len(bodies) != len(req.GetBlockBodiesRequest) {
|
||||||
if len(bodies) != len(req.GetBlockBodiesPacket) {
|
|
||||||
t.Fatalf("wrong bodies in response: expected %d bodies, "+
|
t.Fatalf("wrong bodies in response: expected %d bodies, "+
|
||||||
"got %d", len(req.GetBlockBodiesPacket), len(bodies))
|
"got %d", len(req.GetBlockBodiesRequest), len(bodies))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,8 +520,8 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTxReq := &GetPooledTransactions{
|
getTxReq := &GetPooledTransactions{
|
||||||
RequestId: 1234,
|
RequestId: 1234,
|
||||||
GetPooledTransactionsPacket: hashes,
|
GetPooledTransactionsRequest: hashes,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = conn.Write(getTxReq); err != nil {
|
if err = conn.Write(getTxReq); err != nil {
|
||||||
|
|
@ -536,7 +530,7 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
|
||||||
// check that all received transactions match those that were sent to node
|
// check that all received transactions match those that were sent to node
|
||||||
switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) {
|
switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) {
|
||||||
case *PooledTransactions:
|
case *PooledTransactions:
|
||||||
for _, gotTx := range msg.PooledTransactionsPacket {
|
for _, gotTx := range msg.PooledTransactionsResponse {
|
||||||
if _, exists := hashMap[gotTx.Hash()]; !exists {
|
if _, exists := hashMap[gotTx.Hash()]; !exists {
|
||||||
t.Fatalf("unexpected tx received: %v", gotTx.Hash())
|
t.Fatalf("unexpected tx received: %v", gotTx.Hash())
|
||||||
}
|
}
|
||||||
|
|
@ -600,8 +594,8 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
|
||||||
msg := conn.readAndServe(s.chain, timeout)
|
msg := conn.readAndServe(s.chain, timeout)
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *GetPooledTransactions:
|
case *GetPooledTransactions:
|
||||||
if len(msg.GetPooledTransactionsPacket) != len(hashes) {
|
if len(msg.GetPooledTransactionsRequest) != len(hashes) {
|
||||||
t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsPacket))
|
t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ func setupGeth(stack *node.Node) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
backend.SetSynced()
|
||||||
|
|
||||||
_, err = backend.BlockChain().InsertChain(chain.blocks[1:])
|
_, err = backend.BlockChain().InsertChain(chain.blocks[1:])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,24 +99,24 @@ func (msg Transactions) Code() int { return 18 }
|
||||||
func (msg Transactions) ReqID() uint64 { return 18 }
|
func (msg Transactions) ReqID() uint64 { return 18 }
|
||||||
|
|
||||||
// GetBlockHeaders represents a block header query.
|
// GetBlockHeaders represents a block header query.
|
||||||
type GetBlockHeaders eth.GetBlockHeadersPacket66
|
type GetBlockHeaders eth.GetBlockHeadersPacket
|
||||||
|
|
||||||
func (msg GetBlockHeaders) Code() int { return 19 }
|
func (msg GetBlockHeaders) Code() int { return 19 }
|
||||||
func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
|
func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
||||||
type BlockHeaders eth.BlockHeadersPacket66
|
type BlockHeaders eth.BlockHeadersPacket
|
||||||
|
|
||||||
func (msg BlockHeaders) Code() int { return 20 }
|
func (msg BlockHeaders) Code() int { return 20 }
|
||||||
func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
|
func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
||||||
// GetBlockBodies represents a GetBlockBodies request
|
// GetBlockBodies represents a GetBlockBodies request
|
||||||
type GetBlockBodies eth.GetBlockBodiesPacket66
|
type GetBlockBodies eth.GetBlockBodiesPacket
|
||||||
|
|
||||||
func (msg GetBlockBodies) Code() int { return 21 }
|
func (msg GetBlockBodies) Code() int { return 21 }
|
||||||
func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
|
func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
||||||
// BlockBodies is the network packet for block content distribution.
|
// BlockBodies is the network packet for block content distribution.
|
||||||
type BlockBodies eth.BlockBodiesPacket66
|
type BlockBodies eth.BlockBodiesPacket
|
||||||
|
|
||||||
func (msg BlockBodies) Code() int { return 22 }
|
func (msg BlockBodies) Code() int { return 22 }
|
||||||
func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
|
func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
@ -128,7 +128,7 @@ func (msg NewBlock) Code() int { return 23 }
|
||||||
func (msg NewBlock) ReqID() uint64 { return 0 }
|
func (msg NewBlock) ReqID() uint64 { return 0 }
|
||||||
|
|
||||||
// NewPooledTransactionHashes66 is the network packet for the tx hash propagation message.
|
// NewPooledTransactionHashes66 is the network packet for the tx hash propagation message.
|
||||||
type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket66
|
type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket67
|
||||||
|
|
||||||
func (msg NewPooledTransactionHashes66) Code() int { return 24 }
|
func (msg NewPooledTransactionHashes66) Code() int { return 24 }
|
||||||
func (msg NewPooledTransactionHashes66) ReqID() uint64 { return 0 }
|
func (msg NewPooledTransactionHashes66) ReqID() uint64 { return 0 }
|
||||||
|
|
@ -139,12 +139,12 @@ type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket68
|
||||||
func (msg NewPooledTransactionHashes) Code() int { return 24 }
|
func (msg NewPooledTransactionHashes) Code() int { return 24 }
|
||||||
func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
|
func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
|
||||||
|
|
||||||
type GetPooledTransactions eth.GetPooledTransactionsPacket66
|
type GetPooledTransactions eth.GetPooledTransactionsPacket
|
||||||
|
|
||||||
func (msg GetPooledTransactions) Code() int { return 25 }
|
func (msg GetPooledTransactions) Code() int { return 25 }
|
||||||
func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
|
func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
||||||
type PooledTransactions eth.PooledTransactionsPacket66
|
type PooledTransactions eth.PooledTransactionsPacket
|
||||||
|
|
||||||
func (msg PooledTransactions) Code() int { return 26 }
|
func (msg PooledTransactions) Code() int { return 26 }
|
||||||
func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
|
func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
|
||||||
|
|
@ -181,28 +181,28 @@ func (c *Conn) Read() Message {
|
||||||
case (Status{}).Code():
|
case (Status{}).Code():
|
||||||
msg = new(Status)
|
msg = new(Status)
|
||||||
case (GetBlockHeaders{}).Code():
|
case (GetBlockHeaders{}).Code():
|
||||||
ethMsg := new(eth.GetBlockHeadersPacket66)
|
ethMsg := new(eth.GetBlockHeadersPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*GetBlockHeaders)(ethMsg)
|
return (*GetBlockHeaders)(ethMsg)
|
||||||
case (BlockHeaders{}).Code():
|
case (BlockHeaders{}).Code():
|
||||||
ethMsg := new(eth.BlockHeadersPacket66)
|
ethMsg := new(eth.BlockHeadersPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*BlockHeaders)(ethMsg)
|
return (*BlockHeaders)(ethMsg)
|
||||||
case (GetBlockBodies{}).Code():
|
case (GetBlockBodies{}).Code():
|
||||||
ethMsg := new(eth.GetBlockBodiesPacket66)
|
ethMsg := new(eth.GetBlockBodiesPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*GetBlockBodies)(ethMsg)
|
return (*GetBlockBodies)(ethMsg)
|
||||||
case (BlockBodies{}).Code():
|
case (BlockBodies{}).Code():
|
||||||
ethMsg := new(eth.BlockBodiesPacket66)
|
ethMsg := new(eth.BlockBodiesPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -223,14 +223,14 @@ func (c *Conn) Read() Message {
|
||||||
|
|
||||||
msg = new(NewPooledTransactionHashes66)
|
msg = new(NewPooledTransactionHashes66)
|
||||||
case (GetPooledTransactions{}.Code()):
|
case (GetPooledTransactions{}.Code()):
|
||||||
ethMsg := new(eth.GetPooledTransactionsPacket66)
|
ethMsg := new(eth.GetPooledTransactionsPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*GetPooledTransactions)(ethMsg)
|
return (*GetPooledTransactions)(ethMsg)
|
||||||
case (PooledTransactions{}.Code()):
|
case (PooledTransactions{}.Code()):
|
||||||
ethMsg := new(eth.PooledTransactionsPacket66)
|
ethMsg := new(eth.PooledTransactionsPacket)
|
||||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||||
return errorf("could not rlp decode message: %v", err)
|
return errorf("could not rlp decode message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/forkid"
|
"github.com/ethereum/go-ethereum/core/forkid"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -259,15 +258,13 @@ func ethFilter(args []string) (nodeFilter, error) {
|
||||||
|
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "mainnet":
|
case "mainnet":
|
||||||
filter = forkid.NewStaticFilter(params.MainnetChainConfig, params.MainnetGenesisHash)
|
filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock())
|
||||||
case "goerli":
|
case "goerli":
|
||||||
filter = forkid.NewStaticFilter(params.GoerliChainConfig, params.GoerliGenesisHash)
|
filter = forkid.NewStaticFilter(params.GoerliChainConfig, core.DefaultGoerliGenesisBlock().ToBlock())
|
||||||
case "sepolia":
|
case "sepolia":
|
||||||
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, params.SepoliaGenesisHash)
|
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
|
||||||
case "bor-mumbai":
|
case "holesky":
|
||||||
filter = forkid.NewStaticFilter(params.MumbaiChainConfig, params.MumbaiGenesisHash)
|
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
|
||||||
case "bor-mainnet":
|
|
||||||
filter = forkid.NewStaticFilter(params.BorMainnetChainConfig, params.BorMainnetGenesisHash)
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown network %q", args[0])
|
return nil, fmt.Errorf("unknown network %q", args[0])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/reexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testEthkey struct {
|
type testEthkey struct {
|
||||||
|
|
|
||||||
|
|
@ -21,30 +21,34 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var RunFlag = &cli.StringFlag{
|
||||||
|
Name: "run",
|
||||||
|
Value: ".*",
|
||||||
|
Usage: "Run only those tests matching the regular expression.",
|
||||||
|
}
|
||||||
|
|
||||||
var blockTestCommand = &cli.Command{
|
var blockTestCommand = &cli.Command{
|
||||||
Action: blockTestCmd,
|
Action: blockTestCmd,
|
||||||
Name: "blocktest",
|
Name: "blocktest",
|
||||||
Usage: "executes the given blockchain tests",
|
Usage: "executes the given blockchain tests",
|
||||||
ArgsUsage: "<file>",
|
ArgsUsage: "<file>",
|
||||||
|
Flags: []cli.Flag{RunFlag},
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockTestCmd(ctx *cli.Context) error {
|
func blockTestCmd(ctx *cli.Context) error {
|
||||||
if len(ctx.Args().First()) == 0 {
|
if len(ctx.Args().First()) == 0 {
|
||||||
return errors.New("path-to-test argument required")
|
return errors.New("path-to-test argument required")
|
||||||
}
|
}
|
||||||
// Configure the go-ethereum logger
|
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
|
||||||
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
|
||||||
log.Root().SetHandler(glogger)
|
|
||||||
var tracer vm.EVMLogger
|
var tracer vm.EVMLogger
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
if ctx.Bool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
|
|
@ -66,10 +70,24 @@ func blockTestCmd(ctx *cli.Context) error {
|
||||||
if err = json.Unmarshal(src, &tests); err != nil {
|
if err = json.Unmarshal(src, &tests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
re, err := regexp.Compile(ctx.String(RunFlag.Name))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
// Run them in order
|
||||||
if err := test.Run(false, tracer); err != nil {
|
var keys []string
|
||||||
return fmt.Errorf("test %v: %w", i, err)
|
for key := range tests {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
for _, name := range keys {
|
||||||
|
if !re.MatchString(name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
test := tests[name]
|
||||||
|
if err := test.Run(false, rawdb.HashScheme, tracer); err != nil {
|
||||||
|
return fmt.Errorf("test %v: %w", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,33 +38,38 @@ import (
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
|
//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
|
||||||
type header struct {
|
type header struct {
|
||||||
ParentHash common.Hash `json:"parentHash"`
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
OmmerHash *common.Hash `json:"sha3Uncles"`
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
Coinbase *common.Address `json:"miner"`
|
Coinbase *common.Address `json:"miner"`
|
||||||
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
TxHash *common.Hash `json:"transactionsRoot"`
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
Bloom types.Bloom `json:"logsBloom"`
|
Bloom types.Bloom `json:"logsBloom"`
|
||||||
Difficulty *big.Int `json:"difficulty"`
|
Difficulty *big.Int `json:"difficulty"`
|
||||||
Number *big.Int `json:"number" gencodec:"required"`
|
Number *big.Int `json:"number" gencodec:"required"`
|
||||||
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed uint64 `json:"gasUsed"`
|
GasUsed uint64 `json:"gasUsed"`
|
||||||
Time uint64 `json:"timestamp" gencodec:"required"`
|
Time uint64 `json:"timestamp" gencodec:"required"`
|
||||||
Extra []byte `json:"extraData"`
|
Extra []byte `json:"extraData"`
|
||||||
MixDigest common.Hash `json:"mixHash"`
|
MixDigest common.Hash `json:"mixHash"`
|
||||||
Nonce *types.BlockNonce `json:"nonce"`
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
|
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
|
||||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||||
|
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
|
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type headerMarshaling struct {
|
type headerMarshaling struct {
|
||||||
Difficulty *math.HexOrDecimal256
|
Difficulty *math.HexOrDecimal256
|
||||||
Number *math.HexOrDecimal256
|
Number *math.HexOrDecimal256
|
||||||
GasLimit math.HexOrDecimal64
|
GasLimit math.HexOrDecimal64
|
||||||
GasUsed math.HexOrDecimal64
|
GasUsed math.HexOrDecimal64
|
||||||
Time math.HexOrDecimal64
|
Time math.HexOrDecimal64
|
||||||
Extra hexutil.Bytes
|
Extra hexutil.Bytes
|
||||||
BaseFee *math.HexOrDecimal256
|
BaseFee *math.HexOrDecimal256
|
||||||
|
BlobGasUsed *math.HexOrDecimal64
|
||||||
|
ExcessBlobGas *math.HexOrDecimal64
|
||||||
}
|
}
|
||||||
|
|
||||||
type bbInput struct {
|
type bbInput struct {
|
||||||
|
|
@ -119,22 +124,25 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error {
|
||||||
// ToBlock converts i into a *types.Block
|
// ToBlock converts i into a *types.Block
|
||||||
func (i *bbInput) ToBlock() *types.Block {
|
func (i *bbInput) ToBlock() *types.Block {
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: i.Header.ParentHash,
|
ParentHash: i.Header.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
Coinbase: common.Address{},
|
Coinbase: common.Address{},
|
||||||
Root: i.Header.Root,
|
Root: i.Header.Root,
|
||||||
TxHash: types.EmptyTxsHash,
|
TxHash: types.EmptyTxsHash,
|
||||||
ReceiptHash: types.EmptyReceiptsHash,
|
ReceiptHash: types.EmptyReceiptsHash,
|
||||||
Bloom: i.Header.Bloom,
|
Bloom: i.Header.Bloom,
|
||||||
Difficulty: common.Big0,
|
Difficulty: common.Big0,
|
||||||
Number: i.Header.Number,
|
Number: i.Header.Number,
|
||||||
GasLimit: i.Header.GasLimit,
|
GasLimit: i.Header.GasLimit,
|
||||||
GasUsed: i.Header.GasUsed,
|
GasUsed: i.Header.GasUsed,
|
||||||
Time: i.Header.Time,
|
Time: i.Header.Time,
|
||||||
Extra: i.Header.Extra,
|
Extra: i.Header.Extra,
|
||||||
MixDigest: i.Header.MixDigest,
|
MixDigest: i.Header.MixDigest,
|
||||||
BaseFee: i.Header.BaseFee,
|
BaseFee: i.Header.BaseFee,
|
||||||
WithdrawalsHash: i.Header.WithdrawalsHash,
|
WithdrawalsHash: i.Header.WithdrawalsHash,
|
||||||
|
BlobGasUsed: i.Header.BlobGasUsed,
|
||||||
|
ExcessBlobGas: i.Header.ExcessBlobGas,
|
||||||
|
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill optional values.
|
// Fill optional values.
|
||||||
|
|
@ -160,8 +168,7 @@ func (i *bbInput) ToBlock() *types.Block {
|
||||||
if i.Header.Nonce != nil {
|
if i.Header.Nonce != nil {
|
||||||
header.Nonce = *i.Header.Nonce
|
header.Nonce = *i.Header.Nonce
|
||||||
}
|
}
|
||||||
|
if i.Header.Difficulty != nil {
|
||||||
if header.Difficulty != nil {
|
|
||||||
header.Difficulty = i.Header.Difficulty
|
header.Difficulty = i.Header.Difficulty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type ExecutionResult struct {
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"currentBlobGasUsed,omitempty"`
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
|
|
@ -68,25 +68,26 @@ type ommer struct {
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
|
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *big.Int `json:"currentDifficulty"`
|
Difficulty *big.Int `json:"currentDifficulty"`
|
||||||
Random *big.Int `json:"currentRandom"`
|
Random *big.Int `json:"currentRandom"`
|
||||||
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
||||||
ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number uint64 `json:"currentNumber" gencodec:"required"`
|
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *big.Int `json:"currentBaseFee,omitempty"`
|
BaseFee *big.Int `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *uint64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type stEnvMarshaling struct {
|
type stEnvMarshaling struct {
|
||||||
|
|
@ -114,8 +115,8 @@ type rejectedTx struct {
|
||||||
|
|
||||||
// Apply applies a set of transactions to a pre-state
|
// Apply applies a set of transactions to a pre-state
|
||||||
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
txs types.Transactions, miningReward int64,
|
txIt txIterator, miningReward int64,
|
||||||
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) {
|
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, []byte, error) {
|
||||||
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
||||||
// required blockhashes
|
// required blockhashes
|
||||||
var hashError error
|
var hashError error
|
||||||
|
|
@ -166,8 +167,21 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
rnd := common.BigToHash(pre.Env.Random)
|
rnd := common.BigToHash(pre.Env.Random)
|
||||||
vmContext.Random = &rnd
|
vmContext.Random = &rnd
|
||||||
}
|
}
|
||||||
|
// Calculate the BlobBaseFee
|
||||||
vmContext.ExcessBlobGas = nil
|
var excessBlobGas uint64
|
||||||
|
if pre.Env.ExcessBlobGas != nil {
|
||||||
|
excessBlobGas := *pre.Env.ExcessBlobGas
|
||||||
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
||||||
|
} else {
|
||||||
|
// If it is not explicitly defined, but we have the parent values, we try
|
||||||
|
// to calculate it ourselves.
|
||||||
|
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
|
||||||
|
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
|
||||||
|
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
|
||||||
|
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
|
||||||
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
||||||
|
}
|
||||||
|
}
|
||||||
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
||||||
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
||||||
if chainConfig.DAOForkSupport &&
|
if chainConfig.DAOForkSupport &&
|
||||||
|
|
@ -175,9 +189,20 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||||
|
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
||||||
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
|
}
|
||||||
var blobGasUsed uint64
|
var blobGasUsed uint64
|
||||||
for i, tx := range txs {
|
|
||||||
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
|
for i := 0; txIt.Next(); i++ {
|
||||||
|
tx, err := txIt.Tx()
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("rejected tx", "index", i, "error", err)
|
||||||
|
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil {
|
||||||
errMsg := "blob tx used but field env.ExcessBlobGas missing"
|
errMsg := "blob tx used but field env.ExcessBlobGas missing"
|
||||||
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
|
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
|
||||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
|
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
|
||||||
|
|
@ -190,10 +215,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if tx.Type() == types.BlobTxType {
|
||||||
|
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())
|
tracer, err := getTracerFn(txIndex, tx.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vmConfig.Tracer = tracer
|
vmConfig.Tracer = tracer
|
||||||
|
|
@ -219,13 +253,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if tx.Type() == types.BlobTxType {
|
|
||||||
blobGasUsed += params.BlobTxBlobGasPerBlob
|
|
||||||
}
|
|
||||||
includedTxs = append(includedTxs, tx)
|
includedTxs = append(includedTxs, tx)
|
||||||
|
|
||||||
if hashError != nil {
|
if hashError != nil {
|
||||||
return nil, nil, NewError(ErrorMissingBlockhash, hashError)
|
return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
|
||||||
}
|
}
|
||||||
|
|
||||||
gasUsed += msgResult.UsedGas
|
gasUsed += msgResult.UsedGas
|
||||||
|
|
@ -306,7 +337,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
// Commit block
|
// Commit block
|
||||||
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
execRs := &ExecutionResult{
|
execRs := &ExecutionResult{
|
||||||
|
|
@ -326,17 +357,18 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
|
||||||
execRs.WithdrawalsRoot = &h
|
execRs.WithdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
if vmContext.ExcessBlobGas != nil {
|
if vmContext.BlobBaseFee != nil {
|
||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(vmContext.ExcessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
statedb, err = state.New(root, statedb.Database(), nil)
|
statedb, err = state.New(root, statedb.Database(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
||||||
}
|
}
|
||||||
return statedb, execRs, nil
|
body, _ := rlp.EncodeToBytes(includedTxs)
|
||||||
|
return statedb, execRs, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
|
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
|
||||||
|
|
|
||||||
|
|
@ -18,23 +18,26 @@ var _ = (*headerMarshaling)(nil)
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (h header) MarshalJSON() ([]byte, error) {
|
func (h header) MarshalJSON() ([]byte, error) {
|
||||||
type header struct {
|
type header struct {
|
||||||
ParentHash common.Hash `json:"parentHash"`
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
OmmerHash *common.Hash `json:"sha3Uncles"`
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
Coinbase *common.Address `json:"miner"`
|
Coinbase *common.Address `json:"miner"`
|
||||||
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
TxHash *common.Hash `json:"transactionsRoot"`
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
Bloom types.Bloom `json:"logsBloom"`
|
Bloom types.Bloom `json:"logsBloom"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||||
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
||||||
Extra hexutil.Bytes `json:"extraData"`
|
Extra hexutil.Bytes `json:"extraData"`
|
||||||
MixDigest common.Hash `json:"mixHash"`
|
MixDigest common.Hash `json:"mixHash"`
|
||||||
Nonce *types.BlockNonce `json:"nonce"`
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
||||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||||
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc header
|
var enc header
|
||||||
|
|
@ -55,30 +58,35 @@ func (h header) MarshalJSON() ([]byte, error) {
|
||||||
enc.Nonce = h.Nonce
|
enc.Nonce = h.Nonce
|
||||||
enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee)
|
enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee)
|
||||||
enc.WithdrawalsHash = h.WithdrawalsHash
|
enc.WithdrawalsHash = h.WithdrawalsHash
|
||||||
|
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
|
||||||
|
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
|
||||||
|
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (h *header) UnmarshalJSON(input []byte) error {
|
func (h *header) UnmarshalJSON(input []byte) error {
|
||||||
type header struct {
|
type header struct {
|
||||||
ParentHash *common.Hash `json:"parentHash"`
|
ParentHash *common.Hash `json:"parentHash"`
|
||||||
OmmerHash *common.Hash `json:"sha3Uncles"`
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
Coinbase *common.Address `json:"miner"`
|
Coinbase *common.Address `json:"miner"`
|
||||||
Root *common.Hash `json:"stateRoot" gencodec:"required"`
|
Root *common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
TxHash *common.Hash `json:"transactionsRoot"`
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
Bloom *types.Bloom `json:"logsBloom"`
|
Bloom *types.Bloom `json:"logsBloom"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||||
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
||||||
Extra *hexutil.Bytes `json:"extraData"`
|
Extra *hexutil.Bytes `json:"extraData"`
|
||||||
MixDigest *common.Hash `json:"mixHash"`
|
MixDigest *common.Hash `json:"mixHash"`
|
||||||
Nonce *types.BlockNonce `json:"nonce"`
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
||||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||||
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec header
|
var dec header
|
||||||
|
|
@ -158,6 +166,14 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
||||||
if dec.WithdrawalsHash != nil {
|
if dec.WithdrawalsHash != nil {
|
||||||
h.WithdrawalsHash = dec.WithdrawalsHash
|
h.WithdrawalsHash = dec.WithdrawalsHash
|
||||||
}
|
}
|
||||||
|
if dec.BlobGasUsed != nil {
|
||||||
|
h.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
|
||||||
|
}
|
||||||
|
if dec.ExcessBlobGas != nil {
|
||||||
|
h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
|
}
|
||||||
|
if dec.ParentBeaconBlockRoot != nil {
|
||||||
|
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,26 @@ var _ = (*stEnvMarshaling)(nil)
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (s stEnv) MarshalJSON() ([]byte, error) {
|
func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc stEnv
|
var enc stEnv
|
||||||
|
|
@ -58,31 +59,33 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
|
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
|
||||||
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
||||||
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
||||||
|
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash *common.Hash `json:"parentUncleHash"`
|
ParentUncleHash *common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec stEnv
|
var dec stEnv
|
||||||
|
|
@ -168,5 +171,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ParentBlobGasUsed != nil {
|
if dec.ParentBlobGasUsed != nil {
|
||||||
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
|
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
|
||||||
}
|
}
|
||||||
|
if dec.ParentBeaconBlockRoot != nil {
|
||||||
|
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,12 @@
|
||||||
package t8ntool
|
package t8ntool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
|
@ -35,11 +33,9 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -158,7 +154,7 @@ func Transition(ctx *cli.Context) error {
|
||||||
// Check if anything needs to be read from stdin
|
// Check if anything needs to be read from stdin
|
||||||
var (
|
var (
|
||||||
prestate Prestate
|
prestate Prestate
|
||||||
txs types.Transactions // txs to apply
|
txIt txIterator // txs to apply
|
||||||
allocStr = ctx.String(InputAllocFlag.Name)
|
allocStr = ctx.String(InputAllocFlag.Name)
|
||||||
|
|
||||||
envStr = ctx.String(InputEnvFlag.Name)
|
envStr = ctx.String(InputEnvFlag.Name)
|
||||||
|
|
@ -208,106 +204,71 @@ func Transition(ctx *cli.Context) error {
|
||||||
// Set the chain id
|
// Set the chain id
|
||||||
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
||||||
|
|
||||||
var txsWithKeys []*txWithKey
|
if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
|
||||||
|
return err
|
||||||
if txStr != stdinSelector {
|
|
||||||
inFile, err := os.Open(txStr)
|
|
||||||
if err != nil {
|
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer inFile.Close()
|
|
||||||
decoder := json.NewDecoder(inFile)
|
|
||||||
|
|
||||||
if strings.HasSuffix(txStr, ".rlp") {
|
|
||||||
var body hexutil.Bytes
|
|
||||||
if err := decoder.Decode(&body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var txs types.Transactions
|
|
||||||
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tx := range txs {
|
|
||||||
txsWithKeys = append(txsWithKeys, &txWithKey{
|
|
||||||
key: nil,
|
|
||||||
tx: tx,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := decoder.Decode(&txsWithKeys); err != nil {
|
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(inputData.TxRlp) > 0 {
|
|
||||||
// Decode the body of already signed transactions
|
|
||||||
body := common.FromHex(inputData.TxRlp)
|
|
||||||
|
|
||||||
var txs types.Transactions
|
|
||||||
|
|
||||||
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tx := range txs {
|
|
||||||
txsWithKeys = append(txsWithKeys, &txWithKey{
|
|
||||||
key: nil,
|
|
||||||
tx: tx,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// JSON encoded transactions
|
|
||||||
txsWithKeys = inputData.Txs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// We may have to sign the transactions.
|
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
|
return err
|
||||||
|
}
|
||||||
|
if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Run the test and aggregate the result
|
||||||
|
s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Dump the excution result
|
||||||
|
collector := make(Alloc)
|
||||||
|
s.DumpToCollector(collector, nil)
|
||||||
|
return dispatchOutput(ctx, baseDir, result, collector, body)
|
||||||
|
}
|
||||||
|
|
||||||
if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil {
|
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))
|
if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
// Sanity check, to not `panic` in state_transition
|
// Sanity check, to not `panic` in state_transition
|
||||||
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
if env.BaseFee != nil {
|
||||||
if prestate.Env.BaseFee != nil {
|
// Already set, base fee has precedent over parent base fee.
|
||||||
// Already set, base fee has precedent over parent base fee.
|
return nil
|
||||||
} else if prestate.Env.ParentBaseFee != nil && prestate.Env.Number != 0 {
|
|
||||||
parent := &types.Header{
|
|
||||||
Number: new(big.Int).SetUint64(prestate.Env.Number - 1),
|
|
||||||
BaseFee: prestate.Env.ParentBaseFee,
|
|
||||||
GasUsed: prestate.Env.ParentGasUsed,
|
|
||||||
GasLimit: prestate.Env.ParentGasLimit,
|
|
||||||
}
|
|
||||||
prestate.Env.BaseFee = eip1559.CalcBaseFee(chainConfig, parent)
|
|
||||||
} else {
|
|
||||||
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if env.ParentBaseFee == nil || env.Number == 0 {
|
||||||
|
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
||||||
|
}
|
||||||
|
env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{
|
||||||
|
Number: new(big.Int).SetUint64(env.Number - 1),
|
||||||
|
BaseFee: env.ParentBaseFee,
|
||||||
|
GasUsed: env.ParentGasUsed,
|
||||||
|
GasLimit: env.ParentGasLimit,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if chainConfig.IsShanghai(big.NewInt(int64(prestate.Env.Number))) && prestate.Env.Withdrawals == nil {
|
func applyShanghaiChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
if !chainConfig.IsShanghai(big.NewInt(int64(env.Number)), env.Timestamp) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if env.Withdrawals == nil {
|
||||||
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
|
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
|
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
|
||||||
env := prestate.Env
|
if !isMerged {
|
||||||
|
// pre-merge: If difficulty was not provided by caller, we need to calculate it.
|
||||||
if isMerged {
|
if env.Difficulty != nil {
|
||||||
// post-merge:
|
// already set
|
||||||
// - random must be supplied
|
return nil
|
||||||
// - difficulty must be zero
|
|
||||||
switch {
|
|
||||||
case env.Random == nil:
|
|
||||||
return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
|
|
||||||
case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
|
|
||||||
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prestate.Env.Difficulty = nil
|
|
||||||
} else if env.Difficulty == nil {
|
|
||||||
// pre-merge:
|
|
||||||
// If difficulty was not provided by caller, we need to calculate it.
|
|
||||||
switch {
|
switch {
|
||||||
case env.ParentDifficulty == nil:
|
case env.ParentDifficulty == nil:
|
||||||
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
||||||
|
|
@ -317,114 +278,34 @@ func Transition(ctx *cli.Context) error {
|
||||||
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
||||||
env.Timestamp, env.ParentTimestamp))
|
env.Timestamp, env.ParentTimestamp))
|
||||||
}
|
}
|
||||||
|
env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
||||||
prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
|
||||||
env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash)
|
env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
// Run the test and aggregate the result
|
// post-merge:
|
||||||
s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer)
|
// - random must be supplied
|
||||||
if err != nil {
|
// - difficulty must be zero
|
||||||
return err
|
switch {
|
||||||
|
case env.Random == nil:
|
||||||
|
return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
|
||||||
|
case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
|
||||||
|
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
|
||||||
}
|
}
|
||||||
|
env.Difficulty = nil
|
||||||
body, _ := rlp.EncodeToBytes(txs)
|
|
||||||
// Dump the execution result
|
|
||||||
collector := make(Alloc)
|
|
||||||
s.DumpToCollector(collector, nil)
|
|
||||||
|
|
||||||
return dispatchOutput(ctx, baseDir, result, collector, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
|
|
||||||
// a `secretKey`-field, for input
|
|
||||||
type txWithKey struct {
|
|
||||||
key *ecdsa.PrivateKey
|
|
||||||
tx *types.Transaction
|
|
||||||
protected bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
|
||||||
// Read the metadata, if present
|
|
||||||
type txMetadata struct {
|
|
||||||
Key *common.Hash `json:"secretKey"`
|
|
||||||
Protected *bool `json:"protected"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var data txMetadata
|
|
||||||
if err := json.Unmarshal(input, &data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Key != nil {
|
|
||||||
k := data.Key.Hex()[2:]
|
|
||||||
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
t.key = ecdsaKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Protected != nil {
|
|
||||||
t.protected = *data.Protected
|
|
||||||
} else {
|
|
||||||
t.protected = true
|
|
||||||
}
|
|
||||||
// Now, read the transaction itself
|
|
||||||
var tx types.Transaction
|
|
||||||
if err := json.Unmarshal(input, &tx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.tx = &tx
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// signUnsignedTransactions converts the input txs to canonical transactions.
|
func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
//
|
if !chainConfig.IsCancun(big.NewInt(int64(env.Number)), env.Timestamp) {
|
||||||
// The transactions can have two forms, either
|
env.ParentBeaconBlockRoot = nil // un-set it if it has been set too early
|
||||||
// 1. unsigned or
|
return nil
|
||||||
// 2. signed
|
|
||||||
//
|
|
||||||
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
|
|
||||||
// If so, we sign it here and now, with the given `secretKey`
|
|
||||||
// If the condition above is not met, then it's considered a signed transaction.
|
|
||||||
//
|
|
||||||
// To manage this, we read the transactions twice, first trying to read the secretKeys,
|
|
||||||
// and secondly to read them with the standard tx json format
|
|
||||||
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
|
|
||||||
var signedTxs []*types.Transaction
|
|
||||||
|
|
||||||
for i, txWithKey := range txs {
|
|
||||||
tx := txWithKey.tx
|
|
||||||
key := txWithKey.key
|
|
||||||
v, r, s := tx.RawSignatureValues()
|
|
||||||
|
|
||||||
if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
|
|
||||||
// This transaction needs to be signed
|
|
||||||
var (
|
|
||||||
signed *types.Transaction
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if txWithKey.protected {
|
|
||||||
signed, err = types.SignTx(tx, signer, key)
|
|
||||||
} else {
|
|
||||||
signed, err = types.SignTx(tx, types.FrontierSigner{}, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
signedTxs = append(signedTxs, signed)
|
|
||||||
} else {
|
|
||||||
// Already signed
|
|
||||||
signedTxs = append(signedTxs, tx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Post-cancun
|
||||||
return signedTxs, nil
|
// We require EIP-4788 beacon root to be set in the env
|
||||||
|
if env.ParentBeaconBlockRoot == nil {
|
||||||
|
return NewError(ErrorConfig, errors.New("post-cancun env requires parentBeaconBlockRoot to be set"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Alloc map[common.Address]core.GenesisAccount
|
type Alloc map[common.Address]core.GenesisAccount
|
||||||
|
|
|
||||||
194
cmd/evm/internal/t8ntool/tx_iterator.go
Normal file
194
cmd/evm/internal/t8ntool/tx_iterator.go
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package t8ntool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
|
||||||
|
// a `secretKey`-field, for input
|
||||||
|
type txWithKey struct {
|
||||||
|
key *ecdsa.PrivateKey
|
||||||
|
tx *types.Transaction
|
||||||
|
protected bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
||||||
|
// Read the metadata, if present
|
||||||
|
type txMetadata struct {
|
||||||
|
Key *common.Hash `json:"secretKey"`
|
||||||
|
Protected *bool `json:"protected"`
|
||||||
|
}
|
||||||
|
var data txMetadata
|
||||||
|
if err := json.Unmarshal(input, &data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if data.Key != nil {
|
||||||
|
k := data.Key.Hex()[2:]
|
||||||
|
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
t.key = ecdsaKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if data.Protected != nil {
|
||||||
|
t.protected = *data.Protected
|
||||||
|
} else {
|
||||||
|
t.protected = true
|
||||||
|
}
|
||||||
|
// Now, read the transaction itself
|
||||||
|
var tx types.Transaction
|
||||||
|
if err := json.Unmarshal(input, &tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.tx = &tx
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// signUnsignedTransactions converts the input txs to canonical transactions.
|
||||||
|
//
|
||||||
|
// The transactions can have two forms, either
|
||||||
|
// 1. unsigned or
|
||||||
|
// 2. signed
|
||||||
|
//
|
||||||
|
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
|
||||||
|
// If so, we sign it here and now, with the given `secretKey`
|
||||||
|
// If the condition above is not met, then it's considered a signed transaction.
|
||||||
|
//
|
||||||
|
// To manage this, we read the transactions twice, first trying to read the secretKeys,
|
||||||
|
// and secondly to read them with the standard tx json format
|
||||||
|
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
|
||||||
|
var signedTxs []*types.Transaction
|
||||||
|
for i, tx := range txs {
|
||||||
|
var (
|
||||||
|
v, r, s = tx.tx.RawSignatureValues()
|
||||||
|
signed *types.Transaction
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
|
||||||
|
// Already signed
|
||||||
|
signedTxs = append(signedTxs, tx.tx)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// This transaction needs to be signed
|
||||||
|
if tx.protected {
|
||||||
|
signed, err = types.SignTx(tx.tx, signer, tx.key)
|
||||||
|
} else {
|
||||||
|
signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
||||||
|
}
|
||||||
|
signedTxs = append(signedTxs, signed)
|
||||||
|
}
|
||||||
|
return signedTxs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
|
||||||
|
var txsWithKeys []*txWithKey
|
||||||
|
if txStr != stdinSelector {
|
||||||
|
data, err := os.ReadFile(txStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
|
||||||
|
var body hexutil.Bytes
|
||||||
|
if err := json.Unmarshal(data, &body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newRlpTxIterator(body), nil
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &txsWithKeys); err != nil {
|
||||||
|
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(inputData.TxRlp) > 0 {
|
||||||
|
// Decode the body of already signed transactions
|
||||||
|
return newRlpTxIterator(common.FromHex(inputData.TxRlp)), nil
|
||||||
|
}
|
||||||
|
// JSON encoded transactions
|
||||||
|
txsWithKeys = inputData.Txs
|
||||||
|
}
|
||||||
|
// We may have to sign the transactions.
|
||||||
|
signer := types.LatestSignerForChainID(chainConfig.ChainID)
|
||||||
|
txs, err := signUnsignedTransactions(txsWithKeys, signer)
|
||||||
|
return newSliceTxIterator(txs), err
|
||||||
|
}
|
||||||
|
|
||||||
|
type txIterator interface {
|
||||||
|
// Next returns true until EOF
|
||||||
|
Next() bool
|
||||||
|
// Tx returns the next transaction, OR an error.
|
||||||
|
Tx() (*types.Transaction, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type sliceTxIterator struct {
|
||||||
|
idx int
|
||||||
|
txs []*types.Transaction
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSliceTxIterator(transactions types.Transactions) txIterator {
|
||||||
|
return &sliceTxIterator{0, transactions}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ait *sliceTxIterator) Next() bool {
|
||||||
|
return ait.idx < len(ait.txs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ait *sliceTxIterator) Tx() (*types.Transaction, error) {
|
||||||
|
if ait.idx < len(ait.txs) {
|
||||||
|
ait.idx++
|
||||||
|
return ait.txs[ait.idx-1], nil
|
||||||
|
}
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
type rlpTxIterator struct {
|
||||||
|
in *rlp.Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRlpTxIterator(rlpData []byte) txIterator {
|
||||||
|
in := rlp.NewStream(bytes.NewBuffer(rlpData), 1024*1024)
|
||||||
|
in.List()
|
||||||
|
return &rlpTxIterator{in}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *rlpTxIterator) Next() bool {
|
||||||
|
return it.in.MoreDataInList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *rlpTxIterator) Tx() (*types.Transaction, error) {
|
||||||
|
var a types.Transaction
|
||||||
|
if err := it.in.Decode(&a); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &a, nil
|
||||||
|
}
|
||||||
185
cmd/evm/main.go
185
cmd/evm/main.go
|
|
@ -25,106 +25,115 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DebugFlag = &cli.BoolFlag{
|
DebugFlag = &cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "output full trace logs",
|
Usage: "output full trace logs",
|
||||||
}
|
Category: flags.VMCategory,
|
||||||
MemProfileFlag = &cli.StringFlag{
|
|
||||||
Name: "memprofile",
|
|
||||||
Usage: "creates a memory profile at the given path",
|
|
||||||
}
|
|
||||||
CPUProfileFlag = &cli.StringFlag{
|
|
||||||
Name: "cpuprofile",
|
|
||||||
Usage: "creates a CPU profile at the given path",
|
|
||||||
}
|
}
|
||||||
StatDumpFlag = &cli.BoolFlag{
|
StatDumpFlag = &cli.BoolFlag{
|
||||||
Name: "statdump",
|
Name: "statdump",
|
||||||
Usage: "displays stack and heap memory information",
|
Usage: "displays stack and heap memory information",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
CodeFlag = &cli.StringFlag{
|
CodeFlag = &cli.StringFlag{
|
||||||
Name: "code",
|
Name: "code",
|
||||||
Usage: "EVM code",
|
Usage: "EVM code",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
CodeFileFlag = &cli.StringFlag{
|
CodeFileFlag = &cli.StringFlag{
|
||||||
Name: "codefile",
|
Name: "codefile",
|
||||||
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
GasFlag = &cli.Uint64Flag{
|
GasFlag = &cli.Uint64Flag{
|
||||||
Name: "gas",
|
Name: "gas",
|
||||||
Usage: "gas limit for the evm",
|
Usage: "gas limit for the evm",
|
||||||
Value: 10000000000,
|
Value: 10000000000,
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
PriceFlag = &flags.BigFlag{
|
PriceFlag = &flags.BigFlag{
|
||||||
Name: "price",
|
Name: "price",
|
||||||
Usage: "price set for the evm",
|
Usage: "price set for the evm",
|
||||||
Value: new(big.Int),
|
Value: new(big.Int),
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
ValueFlag = &flags.BigFlag{
|
ValueFlag = &flags.BigFlag{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
Usage: "value set for the evm",
|
Usage: "value set for the evm",
|
||||||
Value: new(big.Int),
|
Value: new(big.Int),
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
DumpFlag = &cli.BoolFlag{
|
DumpFlag = &cli.BoolFlag{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "dumps the state after the run",
|
Usage: "dumps the state after the run",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
InputFlag = &cli.StringFlag{
|
InputFlag = &cli.StringFlag{
|
||||||
Name: "input",
|
Name: "input",
|
||||||
Usage: "input for the EVM",
|
Usage: "input for the EVM",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
InputFileFlag = &cli.StringFlag{
|
InputFileFlag = &cli.StringFlag{
|
||||||
Name: "inputfile",
|
Name: "inputfile",
|
||||||
Usage: "file containing input for the EVM",
|
Usage: "file containing input for the EVM",
|
||||||
}
|
Category: flags.VMCategory,
|
||||||
VerbosityFlag = &cli.IntFlag{
|
|
||||||
Name: "verbosity",
|
|
||||||
Usage: "sets the verbosity level",
|
|
||||||
}
|
}
|
||||||
BenchFlag = &cli.BoolFlag{
|
BenchFlag = &cli.BoolFlag{
|
||||||
Name: "bench",
|
Name: "bench",
|
||||||
Usage: "benchmark the execution",
|
Usage: "benchmark the execution",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
CreateFlag = &cli.BoolFlag{
|
CreateFlag = &cli.BoolFlag{
|
||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "indicates the action should be create rather than call",
|
Usage: "indicates the action should be create rather than call",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
GenesisFlag = &cli.StringFlag{
|
GenesisFlag = &cli.StringFlag{
|
||||||
Name: "prestate",
|
Name: "prestate",
|
||||||
Usage: "JSON file with prestate (genesis) config",
|
Usage: "JSON file with prestate (genesis) config",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
MachineFlag = &cli.BoolFlag{
|
MachineFlag = &cli.BoolFlag{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Usage: "output trace logs in machine readable format (json)",
|
Usage: "output trace logs in machine readable format (json)",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
SenderFlag = &cli.StringFlag{
|
SenderFlag = &cli.StringFlag{
|
||||||
Name: "sender",
|
Name: "sender",
|
||||||
Usage: "The transaction origin",
|
Usage: "The transaction origin",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
ReceiverFlag = &cli.StringFlag{
|
ReceiverFlag = &cli.StringFlag{
|
||||||
Name: "receiver",
|
Name: "receiver",
|
||||||
Usage: "The transaction receiver (execution context)",
|
Usage: "The transaction receiver (execution context)",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
DisableMemoryFlag = &cli.BoolFlag{
|
DisableMemoryFlag = &cli.BoolFlag{
|
||||||
Name: "nomemory",
|
Name: "nomemory",
|
||||||
Value: true,
|
Value: true,
|
||||||
Usage: "disable memory output",
|
Usage: "disable memory output",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
DisableStackFlag = &cli.BoolFlag{
|
DisableStackFlag = &cli.BoolFlag{
|
||||||
Name: "nostack",
|
Name: "nostack",
|
||||||
Usage: "disable stack output",
|
Usage: "disable stack output",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
DisableStorageFlag = &cli.BoolFlag{
|
DisableStorageFlag = &cli.BoolFlag{
|
||||||
Name: "nostorage",
|
Name: "nostorage",
|
||||||
Usage: "disable storage output",
|
Usage: "disable storage output",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
DisableReturnDataFlag = &cli.BoolFlag{
|
DisableReturnDataFlag = &cli.BoolFlag{
|
||||||
Name: "noreturndata",
|
Name: "noreturndata",
|
||||||
Value: true,
|
Value: true,
|
||||||
Usage: "enable return data output",
|
Usage: "enable return data output",
|
||||||
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -184,34 +193,38 @@ var blockBuilderCommand = &cli.Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vmFlags contains flags related to running the EVM.
|
||||||
|
var vmFlags = []cli.Flag{
|
||||||
|
CodeFlag,
|
||||||
|
CodeFileFlag,
|
||||||
|
CreateFlag,
|
||||||
|
GasFlag,
|
||||||
|
PriceFlag,
|
||||||
|
ValueFlag,
|
||||||
|
InputFlag,
|
||||||
|
InputFileFlag,
|
||||||
|
GenesisFlag,
|
||||||
|
SenderFlag,
|
||||||
|
ReceiverFlag,
|
||||||
|
}
|
||||||
|
|
||||||
|
// traceFlags contains flags that configure tracing output.
|
||||||
|
var traceFlags = []cli.Flag{
|
||||||
|
BenchFlag,
|
||||||
|
DebugFlag,
|
||||||
|
DumpFlag,
|
||||||
|
MachineFlag,
|
||||||
|
StatDumpFlag,
|
||||||
|
DisableMemoryFlag,
|
||||||
|
DisableStackFlag,
|
||||||
|
DisableStorageFlag,
|
||||||
|
DisableReturnDataFlag,
|
||||||
|
}
|
||||||
|
|
||||||
var app = flags.NewApp("the evm command line interface")
|
var app = flags.NewApp("the evm command line interface")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags)
|
||||||
BenchFlag,
|
|
||||||
CreateFlag,
|
|
||||||
DebugFlag,
|
|
||||||
VerbosityFlag,
|
|
||||||
CodeFlag,
|
|
||||||
CodeFileFlag,
|
|
||||||
GasFlag,
|
|
||||||
PriceFlag,
|
|
||||||
ValueFlag,
|
|
||||||
DumpFlag,
|
|
||||||
InputFlag,
|
|
||||||
InputFileFlag,
|
|
||||||
MemProfileFlag,
|
|
||||||
CPUProfileFlag,
|
|
||||||
StatDumpFlag,
|
|
||||||
GenesisFlag,
|
|
||||||
MachineFlag,
|
|
||||||
SenderFlag,
|
|
||||||
ReceiverFlag,
|
|
||||||
DisableMemoryFlag,
|
|
||||||
DisableStackFlag,
|
|
||||||
DisableStorageFlag,
|
|
||||||
DisableReturnDataFlag,
|
|
||||||
}
|
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
compileCommand,
|
compileCommand,
|
||||||
disasmCommand,
|
disasmCommand,
|
||||||
|
|
@ -222,6 +235,14 @@ func init() {
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
blockBuilderCommand,
|
blockBuilderCommand,
|
||||||
}
|
}
|
||||||
|
app.Before = func(ctx *cli.Context) error {
|
||||||
|
flags.MigrateGlobalFlags(ctx)
|
||||||
|
return debug.Setup(ctx)
|
||||||
|
}
|
||||||
|
app.After = func(ctx *cli.Context) error {
|
||||||
|
debug.Exit()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"runtime/pprof"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -36,14 +35,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"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/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var runCommand = &cli.Command{
|
var runCommand = &cli.Command{
|
||||||
|
|
@ -52,6 +51,7 @@ var runCommand = &cli.Command{
|
||||||
Usage: "run arbitrary evm binary",
|
Usage: "run arbitrary evm binary",
|
||||||
ArgsUsage: "<code>",
|
ArgsUsage: "<code>",
|
||||||
Description: `The run command runs arbitrary EVM code.`,
|
Description: `The run command runs arbitrary EVM code.`,
|
||||||
|
Flags: flags.Merge(vmFlags, traceFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
// readGenesis will read the given JSON format genesis file and return
|
// readGenesis will read the given JSON format genesis file and return
|
||||||
|
|
@ -115,10 +115,6 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []by
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(ctx *cli.Context) error {
|
func runCmd(ctx *cli.Context) error {
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
|
||||||
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
|
||||||
log.Root().SetHandler(glogger)
|
|
||||||
|
|
||||||
logconfig := &logger.Config{
|
logconfig := &logger.Config{
|
||||||
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||||
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||||
|
|
@ -128,15 +124,15 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tracer vm.EVMLogger
|
tracer vm.EVMLogger
|
||||||
debugLogger *logger.StructLogger
|
debugLogger *logger.StructLogger
|
||||||
statedb *state.StateDB
|
statedb *state.StateDB
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
sender = common.BytesToAddress([]byte("sender"))
|
sender = common.BytesToAddress([]byte("sender"))
|
||||||
receiver = common.BytesToAddress([]byte("receiver"))
|
receiver = common.BytesToAddress([]byte("receiver"))
|
||||||
genesisConfig *core.Genesis
|
preimages = ctx.Bool(DumpFlag.Name)
|
||||||
preimages = ctx.Bool(DumpFlag.Name)
|
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
|
||||||
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
|
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
|
||||||
)
|
)
|
||||||
|
|
||||||
if ctx.Bool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
|
|
@ -148,20 +144,29 @@ func runCmd(ctx *cli.Context) error {
|
||||||
debugLogger = logger.NewStructLogger(logconfig)
|
debugLogger = logger.NewStructLogger(logconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialGas := ctx.Uint64(GasFlag.Name)
|
||||||
|
genesisConfig := new(core.Genesis)
|
||||||
|
genesisConfig.GasLimit = initialGas
|
||||||
if ctx.String(GenesisFlag.Name) != "" {
|
if ctx.String(GenesisFlag.Name) != "" {
|
||||||
gen := readGenesis(ctx.String(GenesisFlag.Name))
|
genesisConfig = readGenesis(ctx.String(GenesisFlag.Name))
|
||||||
genesisConfig = gen
|
if genesisConfig.GasLimit != 0 {
|
||||||
db := rawdb.NewMemoryDatabase()
|
initialGas = genesisConfig.GasLimit
|
||||||
genesis := gen.MustCommit(db)
|
}
|
||||||
sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: preimages})
|
|
||||||
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
|
||||||
chainConfig = gen.Config
|
|
||||||
} else {
|
} else {
|
||||||
sdb := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: preimages})
|
genesisConfig.Config = params.AllEthashProtocolChanges
|
||||||
statedb, _ = state.New(types.EmptyRootHash, sdb, nil)
|
|
||||||
genesisConfig = new(core.Genesis)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
triedb := trie.NewDatabase(db, &trie.Config{
|
||||||
|
Preimages: preimages,
|
||||||
|
HashDB: hashdb.Defaults,
|
||||||
|
})
|
||||||
|
defer triedb.Close()
|
||||||
|
genesis := genesisConfig.MustCommit(db, triedb)
|
||||||
|
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||||
|
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
||||||
|
chainConfig = genesisConfig.Config
|
||||||
|
|
||||||
if ctx.String(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
@ -222,12 +227,6 @@ func runCmd(ctx *cli.Context) error {
|
||||||
|
|
||||||
code = common.Hex2Bytes(bin)
|
code = common.Hex2Bytes(bin)
|
||||||
}
|
}
|
||||||
|
|
||||||
initialGas := ctx.Uint64(GasFlag.Name)
|
|
||||||
if genesisConfig.GasLimit != 0 {
|
|
||||||
initialGas = genesisConfig.GasLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
runtimeConfig := runtime.Config{
|
runtimeConfig := runtime.Config{
|
||||||
Origin: sender,
|
Origin: sender,
|
||||||
State: statedb,
|
State: statedb,
|
||||||
|
|
@ -239,26 +238,12 @@ func runCmd(ctx *cli.Context) error {
|
||||||
Coinbase: genesisConfig.Coinbase,
|
Coinbase: genesisConfig.Coinbase,
|
||||||
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
||||||
BlobHashes: blobHashes,
|
BlobHashes: blobHashes,
|
||||||
|
BlobBaseFee: blobBaseFee,
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: tracer,
|
Tracer: tracer,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" {
|
|
||||||
f, err := os.Create(cpuProfilePath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("could not create CPU profile: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pprof.StartCPUProfile(f); err != nil {
|
|
||||||
fmt.Println("could not start CPU profile: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer pprof.StopCPUProfile()
|
|
||||||
}
|
|
||||||
|
|
||||||
if chainConfig != nil {
|
if chainConfig != nil {
|
||||||
runtimeConfig.ChainConfig = chainConfig
|
runtimeConfig.ChainConfig = chainConfig
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -312,21 +297,6 @@ func runCmd(ctx *cli.Context) error {
|
||||||
fmt.Println(string(statedb.Dump(nil)))
|
fmt.Println(string(statedb.Dump(nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" {
|
|
||||||
f, err := os.Create(memProfilePath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("could not create memory profile: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
|
||||||
fmt.Println("could not write memory profile: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Bool(DebugFlag.Name) {
|
if ctx.Bool(DebugFlag.Name) {
|
||||||
if debugLogger != nil {
|
if debugLogger != nil {
|
||||||
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,11 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -51,11 +52,6 @@ type StatetestResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func stateTestCmd(ctx *cli.Context) error {
|
func stateTestCmd(ctx *cli.Context) error {
|
||||||
// Configure the go-ethereum logger
|
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
|
||||||
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
|
||||||
log.Root().SetHandler(glogger)
|
|
||||||
|
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
config := &logger.Config{
|
config := &logger.Config{
|
||||||
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||||
|
|
@ -107,26 +103,24 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
|
||||||
for _, st := range test.Subtests() {
|
for _, st := range test.Subtests() {
|
||||||
// Run the test and aggregate the result
|
// Run the test and aggregate the result
|
||||||
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
||||||
_, s, err := test.Run(st, cfg, false)
|
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
|
||||||
// print state root for evmlab tracing
|
if state != nil {
|
||||||
if s != nil {
|
root := state.IntermediateRoot(false)
|
||||||
root := s.IntermediateRoot(false)
|
result.Root = &root
|
||||||
result.Root = &root
|
if jsonOut {
|
||||||
if jsonOut {
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
}
|
||||||
}
|
}
|
||||||
}
|
// Dump any state to aid debugging
|
||||||
|
if dump {
|
||||||
if err != nil {
|
dump := state.RawDump(nil)
|
||||||
// Test failed, mark as so and dump any state to aid debugging
|
|
||||||
result.Pass, result.Error = false, err.Error()
|
|
||||||
if dump && s != nil {
|
|
||||||
s, _ = state.New(*result.Root, s.Database(), nil)
|
|
||||||
dump := s.RawDump(nil)
|
|
||||||
result.State = &dump
|
result.State = &dump
|
||||||
}
|
}
|
||||||
}
|
if err != nil {
|
||||||
|
// Test failed, mark as so
|
||||||
|
result.Pass, result.Error = false, err.Error()
|
||||||
|
}
|
||||||
|
})
|
||||||
results = append(results, *result)
|
results = append(results, *result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
||||||
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/reexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
@ -278,6 +278,22 @@ func TestT8n(t *testing.T) {
|
||||||
output: t8nOutput{alloc: true, result: true},
|
output: t8nOutput{alloc: true, result: true},
|
||||||
expOut: "exp.json",
|
expOut: "exp.json",
|
||||||
},
|
},
|
||||||
|
{ // More cancun tests
|
||||||
|
base: "./testdata/29",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs.json", "env.json", "Cancun", "",
|
||||||
|
},
|
||||||
|
output: t8nOutput{alloc: true, result: true},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
|
{ // More cancun test, plus example of rlp-transaction that cannot be decoded properly
|
||||||
|
base: "./testdata/30",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs_more.rlp", "env.json", "Cancun", "",
|
||||||
|
},
|
||||||
|
output: t8nOutput{alloc: true, result: true},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
args := []string{"t8n"}
|
args := []string{"t8n"}
|
||||||
args = append(args, tc.output.get()...)
|
args = append(args, tc.output.get()...)
|
||||||
|
|
|
||||||
8
cmd/evm/testdata/28/env.json
vendored
8
cmd/evm/testdata/28/env.json
vendored
|
|
@ -9,8 +9,7 @@
|
||||||
"parentDifficulty" : "0x00",
|
"parentDifficulty" : "0x00",
|
||||||
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"withdrawals" : [
|
"withdrawals" : [],
|
||||||
],
|
|
||||||
"parentBaseFee" : "0x0a",
|
"parentBaseFee" : "0x0a",
|
||||||
"parentGasUsed" : "0x00",
|
"parentGasUsed" : "0x00",
|
||||||
"parentGasLimit" : "0x7fffffffffffffff",
|
"parentGasLimit" : "0x7fffffffffffffff",
|
||||||
|
|
@ -18,5 +17,6 @@
|
||||||
"parentBlobGasUsed" : "0x00",
|
"parentBlobGasUsed" : "0x00",
|
||||||
"blockHashes" : {
|
"blockHashes" : {
|
||||||
"0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6"
|
"0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6"
|
||||||
}
|
},
|
||||||
}
|
"parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
}
|
||||||
|
|
|
||||||
4
cmd/evm/testdata/28/exp.json
vendored
4
cmd/evm/testdata/28/exp.json
vendored
|
|
@ -42,6 +42,6 @@
|
||||||
"currentBaseFee": "0x9",
|
"currentBaseFee": "0x9",
|
||||||
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"currentExcessBlobGas": "0x0",
|
"currentExcessBlobGas": "0x0",
|
||||||
"currentBlobGasUsed": "0x20000"
|
"blobGasUsed": "0x20000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
cmd/evm/testdata/29/alloc.json
vendored
Normal file
16
cmd/evm/testdata/29/alloc.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x016345785d8a0000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" : {
|
||||||
|
"balance" : "0x1",
|
||||||
|
"code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
cmd/evm/testdata/29/env.json
vendored
Normal file
20
cmd/evm/testdata/29/env.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x079e",
|
||||||
|
"currentGasLimit" : "0x7fffffffffffffff",
|
||||||
|
"previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6",
|
||||||
|
"currentBlobGasUsed" : "0x00",
|
||||||
|
"parentTimestamp" : "0x03b6",
|
||||||
|
"parentDifficulty" : "0x00",
|
||||||
|
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"withdrawals" : [
|
||||||
|
],
|
||||||
|
"parentBaseFee" : "0x0a",
|
||||||
|
"parentGasUsed" : "0x00",
|
||||||
|
"parentGasLimit" : "0x7fffffffffffffff",
|
||||||
|
"parentExcessBlobGas" : "0x00",
|
||||||
|
"parentBlobGasUsed" : "0x00",
|
||||||
|
"parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
}
|
||||||
45
cmd/evm/testdata/29/exp.json
vendored
Normal file
45
cmd/evm/testdata/29/exp.json
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"storage": {
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
},
|
||||||
|
"balance": "0x1"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0x16345785d871db8",
|
||||||
|
"nonce": "0x1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0x19a4f821a7c0a6f4c934f9acb0fe9ce5417b68086e12513ecbc3e3f57e01573c",
|
||||||
|
"txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab",
|
||||||
|
"receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0x5208",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentDifficulty": null,
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"currentBaseFee": "0x9",
|
||||||
|
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"currentExcessBlobGas": "0x0",
|
||||||
|
"blobGasUsed": "0x0"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
cmd/evm/testdata/29/readme.md
vendored
Normal file
29
cmd/evm/testdata/29/readme.md
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
## EIP 4788
|
||||||
|
|
||||||
|
This test contains testcases for EIP-4788. The 4788-contract is
|
||||||
|
located at address `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`, and this test executes a simple transaction. It also
|
||||||
|
implicitly invokes the system tx, which sets calls the contract and sets the
|
||||||
|
storage values
|
||||||
|
|
||||||
|
```
|
||||||
|
$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout
|
||||||
|
INFO [09-27|15:34:53.049] Trie dumping started root=19a4f8..01573c
|
||||||
|
INFO [09-27|15:34:53.049] Trie dumping complete accounts=2 elapsed="192.759µs"
|
||||||
|
INFO [09-27|15:34:53.050] Wrote file file=result.json
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"storage": {
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
},
|
||||||
|
"balance": "0x1"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0x16345785d871db8",
|
||||||
|
"nonce": "0x1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
19
cmd/evm/testdata/29/txs.json
vendored
Normal file
19
cmd/evm/testdata/29/txs.json
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x10000000",
|
||||||
|
"nonce" : "0x0",
|
||||||
|
"to" : "0x1111111111111111111111111111111111111111",
|
||||||
|
"value" : "0x0",
|
||||||
|
"secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"chainId" : "0x1",
|
||||||
|
"type" : "0x2",
|
||||||
|
"v": "0x0",
|
||||||
|
"r": "0x0",
|
||||||
|
"s": "0x0",
|
||||||
|
"maxFeePerGas" : "0xfa0",
|
||||||
|
"maxPriorityFeePerGas" : "0x0",
|
||||||
|
"accessList" : [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
77
cmd/evm/testdata/30/README.txt
vendored
Normal file
77
cmd/evm/testdata/30/README.txt
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
This example comes from https://github.com/ethereum/go-ethereum/issues/27730.
|
||||||
|
The input transactions contain three transactions, number `0` and `2` are taken from
|
||||||
|
`testdata/13`, whereas number `1` is taken from #27730.
|
||||||
|
|
||||||
|
The problematic second transaction cannot be RLP-decoded, and the expectation is
|
||||||
|
that that particular transaction should be rejected, but number `0` and `1` should
|
||||||
|
still be accepted.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go run . t8n --input.alloc=./testdata/30/alloc.json --input.txs=./testdata/30/txs_more.rlp --input.env=./testdata/30/env.json --output.result=stdout --output.alloc=stdout --state.fork=Cancun
|
||||||
|
WARN [10-22|15:38:03.283] rejected tx index=1 error="rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
|
||||||
|
INFO [10-22|15:38:03.284] Trie dumping started root=348312..915c93
|
||||||
|
INFO [10-22|15:38:03.284] Trie dumping complete accounts=3 elapsed="160.831µs"
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87": {
|
||||||
|
"code": "0x60004960005500",
|
||||||
|
"balance": "0xde0b6b3a7640000"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0xde0b6b3a7640000"
|
||||||
|
},
|
||||||
|
"0xd02d72e067e77158444ef2020ff2d325f929b363": {
|
||||||
|
"balance": "0xfffffffb8390",
|
||||||
|
"nonce": "0x3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93",
|
||||||
|
"txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
|
||||||
|
"receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0x5208",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0xa410",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rejected": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentDifficulty": null,
|
||||||
|
"gasUsed": "0xa410",
|
||||||
|
"currentBaseFee": "0x7",
|
||||||
|
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
23
cmd/evm/testdata/30/alloc.json
vendored
Normal file
23
cmd/evm/testdata/30/alloc.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
|
||||||
|
"balance" : "0x0de0b6b3a7640000",
|
||||||
|
"code" : "0x60004960005500",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xd02d72e067e77158444ef2020ff2d325f929b363" : {
|
||||||
|
"balance": "0x01000000000000",
|
||||||
|
"code": "0x",
|
||||||
|
"nonce": "0x01",
|
||||||
|
"storage": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x0de0b6b3a7640000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
cmd/evm/testdata/30/env.json
vendored
Normal file
23
cmd/evm/testdata/30/env.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x03e8",
|
||||||
|
"currentGasLimit" : "0x1000000000",
|
||||||
|
"previousHash" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da",
|
||||||
|
"currentDataGasUsed" : "0x2000",
|
||||||
|
"parentTimestamp" : "0x00",
|
||||||
|
"parentDifficulty" : "0x00",
|
||||||
|
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"parentBeaconBlockRoot" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000",
|
||||||
|
"withdrawals" : [
|
||||||
|
],
|
||||||
|
"parentBaseFee" : "0x08",
|
||||||
|
"parentGasUsed" : "0x00",
|
||||||
|
"parentGasLimit" : "0x1000000000",
|
||||||
|
"parentExcessBlobGas" : "0x1000",
|
||||||
|
"parentBlobGasUsed" : "0x2000",
|
||||||
|
"blockHashes" : {
|
||||||
|
"0" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da"
|
||||||
|
}
|
||||||
|
}
|
||||||
64
cmd/evm/testdata/30/exp.json
vendored
Normal file
64
cmd/evm/testdata/30/exp.json
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87": {
|
||||||
|
"code": "0x60004960005500",
|
||||||
|
"balance": "0xde0b6b3a7640000"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0xde0b6b3a7640000"
|
||||||
|
},
|
||||||
|
"0xd02d72e067e77158444ef2020ff2d325f929b363": {
|
||||||
|
"balance": "0xfffffffb8390",
|
||||||
|
"nonce": "0x3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93",
|
||||||
|
"txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
|
||||||
|
"receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0x5208",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0xa410",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rejected": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentDifficulty": null,
|
||||||
|
"gasUsed": "0xa410",
|
||||||
|
"currentBaseFee": "0x7",
|
||||||
|
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"currentExcessBlobGas": "0x0",
|
||||||
|
"blobGasUsed": "0x0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
cmd/evm/testdata/30/txs.rlp
vendored
Normal file
1
cmd/evm/testdata/30/txs.rlp
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"0xf8dbb8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67"
|
||||||
1
cmd/evm/testdata/30/txs_more.rlp
vendored
Normal file
1
cmd/evm/testdata/30/txs_more.rlp
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"0xf901adb86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9"
|
||||||
2
cmd/evm/testdata/8/readme.md
vendored
2
cmd/evm/testdata/8/readme.md
vendored
|
|
@ -32,7 +32,7 @@ dir=./testdata/8 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json
|
||||||
{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"}
|
{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"}
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly, we can provide the input transactions via `stdin` instead of as file:
|
Similarly, we can provide the input transactions via `stdin` instead of as file:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ dir=./testdata/8 \
|
$ dir=./testdata/8 \
|
||||||
|
|
|
||||||
2
cmd/evm/testdata/9/readme.md
vendored
2
cmd/evm/testdata/9/readme.md
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
## EIP-1559 testing
|
## EIP-1559 testing
|
||||||
|
|
||||||
This test contains testcases for EIP-1559, which uses an new transaction type and has a new block parameter.
|
This test contains testcases for EIP-1559, which uses a new transaction type and has a new block parameter.
|
||||||
|
|
||||||
### Prestate
|
### Prestate
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -50,7 +50,11 @@ var (
|
||||||
Name: "init",
|
Name: "init",
|
||||||
Usage: "Bootstrap and initialize a new genesis block",
|
Usage: "Bootstrap and initialize a new genesis block",
|
||||||
ArgsUsage: "<genesisPath>",
|
ArgsUsage: "<genesisPath>",
|
||||||
Flags: flags.Merge([]cli.Flag{utils.CachePreimagesFlag}, utils.DatabasePathFlags),
|
Flags: flags.Merge([]cli.Flag{
|
||||||
|
utils.CachePreimagesFlag,
|
||||||
|
utils.OverrideCancun,
|
||||||
|
utils.OverrideVerkle,
|
||||||
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The init command initializes a new genesis block and definition for the network.
|
The init command initializes a new genesis block and definition for the network.
|
||||||
This is a destructive action and changes the network in which you will be
|
This is a destructive action and changes the network in which you will be
|
||||||
|
|
@ -95,7 +99,9 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
||||||
utils.MetricsInfluxDBBucketFlag,
|
utils.MetricsInfluxDBBucketFlag,
|
||||||
utils.MetricsInfluxDBOrganizationFlag,
|
utils.MetricsInfluxDBOrganizationFlag,
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
}, utils.DatabasePathFlags),
|
utils.TransactionHistoryFlag,
|
||||||
|
utils.StateHistoryFlag,
|
||||||
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The import command imports blocks from an RLP-encoded form. The form can be one file
|
The import command imports blocks from an RLP-encoded form. The form can be one file
|
||||||
with several RLP-encoded blocks, or several files can be used.
|
with several RLP-encoded blocks, or several files can be used.
|
||||||
|
|
@ -111,7 +117,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
Requires a first argument of the file to write to.
|
Requires a first argument of the file to write to.
|
||||||
Optional second and third arguments control the first and
|
Optional second and third arguments control the first and
|
||||||
|
|
@ -127,7 +133,7 @@ be gzipped.`,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The import-preimages command imports hash preimages from an RLP encoded stream.
|
The import-preimages command imports hash preimages from an RLP encoded stream.
|
||||||
It's deprecated, please use "geth db import" instead.
|
It's deprecated, please use "geth db import" instead.
|
||||||
|
|
@ -141,7 +147,7 @@ It's deprecated, please use "geth db import" instead.
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The export-preimages command exports hash preimages to an RLP encoded stream.
|
The export-preimages command exports hash preimages to an RLP encoded stream.
|
||||||
It's deprecated, please use "geth db export" instead.
|
It's deprecated, please use "geth db export" instead.
|
||||||
|
|
@ -160,7 +166,7 @@ It's deprecated, please use "geth db export" instead.
|
||||||
utils.IncludeIncompletesFlag,
|
utils.IncludeIncompletesFlag,
|
||||||
utils.StartKeyFlag,
|
utils.StartKeyFlag,
|
||||||
utils.DumpLimitFlag,
|
utils.DumpLimitFlag,
|
||||||
}, utils.DatabasePathFlags),
|
}, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
This command dumps out the state for a given block (or latest, if none provided).
|
This command dumps out the state for a given block (or latest, if none provided).
|
||||||
`,
|
`,
|
||||||
|
|
@ -194,22 +200,29 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
|
var overrides core.ChainOverrides
|
||||||
|
if ctx.IsSet(utils.OverrideCancun.Name) {
|
||||||
|
v := ctx.Uint64(utils.OverrideCancun.Name)
|
||||||
|
overrides.OverrideCancun = &v
|
||||||
|
}
|
||||||
|
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||||
|
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||||
|
overrides.OverrideVerkle = &v
|
||||||
|
}
|
||||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||||
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, rawdb.ExtraDBConfig{})
|
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, rawdb.ExtraDBConfig{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to open database: %v", err)
|
utils.Fatalf("Failed to open database: %v", err)
|
||||||
}
|
}
|
||||||
|
defer chaindb.Close()
|
||||||
|
|
||||||
triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false)
|
||||||
Preimages: ctx.Bool(utils.CachePreimagesFlag.Name),
|
defer triedb.Close()
|
||||||
})
|
|
||||||
|
|
||||||
_, hash, err := core.SetupGenesisBlock(chaindb, triedb, genesis)
|
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chaindb.Close()
|
|
||||||
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
|
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,9 +270,7 @@ func dumpGenesis(ctx *cli.Context) error {
|
||||||
if ctx.IsSet(utils.DataDirFlag.Name) {
|
if ctx.IsSet(utils.DataDirFlag.Name) {
|
||||||
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
|
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
|
||||||
}
|
}
|
||||||
|
utils.Fatalf("no network preset provided, no existing genesis in the default datadir")
|
||||||
utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -357,7 +368,8 @@ func exportChain(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chain, _ := utils.MakeChain(ctx, stack, true)
|
chain, db := utils.MakeChain(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -405,6 +417,7 @@ func importPreimages(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, false)
|
db := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
|
defer db.Close()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
|
if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
|
||||||
|
|
@ -426,6 +439,7 @@ func exportPreimages(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
|
if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
|
||||||
|
|
@ -439,6 +453,7 @@ func exportPreimages(ctx *cli.Context) error {
|
||||||
|
|
||||||
func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) {
|
func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) {
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
|
|
||||||
|
|
@ -514,12 +529,10 @@ func dump(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, db, true, true) // always enable preimage lookup
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
config := &trie.Config{
|
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||||
Preimages: true, // always enable preimage lookup
|
|
||||||
}
|
|
||||||
|
|
||||||
state, err := state.New(root, state.NewDatabaseWithConfig(db, config), nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,18 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/external"
|
"github.com/ethereum/go-ethereum/accounts/external"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
||||||
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/eth/catalyst"
|
"github.com/ethereum/go-ethereum/eth/catalyst"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
|
|
@ -41,6 +42,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/naoina/toml"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -167,6 +170,20 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||||
|
|
||||||
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
||||||
|
|
||||||
|
// Create gauge with geth system and build information
|
||||||
|
if eth != nil { // The 'eth' backend may be nil in light mode
|
||||||
|
var protos []string
|
||||||
|
for _, p := range eth.Protocols() {
|
||||||
|
protos = append(protos, fmt.Sprintf("%v/%d", p.Name, p.Version))
|
||||||
|
}
|
||||||
|
metrics.NewRegisteredGaugeInfo("geth/info", nil).Update(metrics.GaugeInfoValue{
|
||||||
|
"arch": runtime.GOARCH,
|
||||||
|
"os": runtime.GOOS,
|
||||||
|
"version": cfg.Node.Version,
|
||||||
|
"protocols": strings.Join(protos, ","),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Configure log filter RPC API.
|
// Configure log filter RPC API.
|
||||||
filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth)
|
filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth)
|
||||||
|
|
||||||
|
|
@ -174,17 +191,18 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||||
if ctx.IsSet(utils.GraphQLEnabledFlag.Name) {
|
if ctx.IsSet(utils.GraphQLEnabledFlag.Name) {
|
||||||
utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node)
|
utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the Ethereum Stats daemon if requested.
|
// Add the Ethereum Stats daemon if requested.
|
||||||
if cfg.Ethstats.URL != "" {
|
if cfg.Ethstats.URL != "" {
|
||||||
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
|
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure full-sync tester service if requested
|
// Configure full-sync tester service if requested
|
||||||
if ctx.IsSet(utils.SyncTargetFlag.Name) && cfg.Eth.SyncMode == downloader.FullSync {
|
if ctx.IsSet(utils.SyncTargetFlag.Name) {
|
||||||
utils.RegisterFullSyncTester(stack, eth, ctx.Path(utils.SyncTargetFlag.Name))
|
hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name))
|
||||||
|
if len(hex) != common.HashLength {
|
||||||
|
utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength)
|
||||||
|
}
|
||||||
|
utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the dev mode if requested, or launch the engine API for
|
// Start the dev mode if requested, or launch the engine API for
|
||||||
// interacting with external consensus client.
|
// interacting with external consensus client.
|
||||||
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ var (
|
||||||
Name: "removedb",
|
Name: "removedb",
|
||||||
Usage: "Remove blockchain and state databases",
|
Usage: "Remove blockchain and state databases",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: utils.DatabasePathFlags,
|
Flags: utils.DatabaseFlags,
|
||||||
Description: `
|
Description: `
|
||||||
Remove blockchain and state databases`,
|
Remove blockchain and state databases`,
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ Remove blockchain and state databases`,
|
||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Usage: "Inspect the storage size for each type of data in the database",
|
Usage: "Inspect the storage size for each type of data in the database",
|
||||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ Remove blockchain and state databases`,
|
||||||
Action: checkStateContent,
|
Action: checkStateContent,
|
||||||
Name: "check-state-content",
|
Name: "check-state-content",
|
||||||
ArgsUsage: "<start (optional)>",
|
ArgsUsage: "<start (optional)>",
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Usage: "Verify that state data is cryptographically correct",
|
Usage: "Verify that state data is cryptographically correct",
|
||||||
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
|
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
|
||||||
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
||||||
|
|
@ -97,7 +97,7 @@ a data corruption.`,
|
||||||
Usage: "Print leveldb statistics",
|
Usage: "Print leveldb statistics",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
}
|
}
|
||||||
dbCompactCmd = &cli.Command{
|
dbCompactCmd = &cli.Command{
|
||||||
Action: dbCompact,
|
Action: dbCompact,
|
||||||
|
|
@ -107,7 +107,7 @@ a data corruption.`,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `This command performs a database compaction.
|
Description: `This command performs a database compaction.
|
||||||
WARNING: This operation may take a very long time to finish, and may cause database
|
WARNING: This operation may take a very long time to finish, and may cause database
|
||||||
corruption if it is aborted during execution'!`,
|
corruption if it is aborted during execution'!`,
|
||||||
|
|
@ -119,7 +119,7 @@ corruption if it is aborted during execution'!`,
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDeleteCmd = &cli.Command{
|
dbDeleteCmd = &cli.Command{
|
||||||
|
|
@ -129,7 +129,7 @@ corruption if it is aborted during execution'!`,
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `This command deletes the specified database key from the database.
|
Description: `This command deletes the specified database key from the database.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +140,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `This command sets a given database key to the given value.
|
Description: `This command sets a given database key to the given value.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +151,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDumpFreezerIndex = &cli.Command{
|
dbDumpFreezerIndex = &cli.Command{
|
||||||
|
|
@ -161,7 +161,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
}
|
}
|
||||||
dbImportCmd = &cli.Command{
|
dbImportCmd = &cli.Command{
|
||||||
|
|
@ -171,7 +171,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
ArgsUsage: "<dumpfile> <start (optional)",
|
ArgsUsage: "<dumpfile> <start (optional)",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
||||||
}
|
}
|
||||||
dbExportCmd = &cli.Command{
|
dbExportCmd = &cli.Command{
|
||||||
|
|
@ -181,7 +181,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
ArgsUsage: "<type> <dumpfile>",
|
ArgsUsage: "<type> <dumpfile>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
||||||
}
|
}
|
||||||
dbMetadataCmd = &cli.Command{
|
dbMetadataCmd = &cli.Command{
|
||||||
|
|
@ -190,7 +190,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Usage: "Shows metadata about the chain status.",
|
Usage: "Shows metadata about the chain status.",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "Shows metadata about the chain status.",
|
Description: "Shows metadata about the chain status.",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -523,6 +523,9 @@ func dbDumpTrie(ctx *cli.Context) error {
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, db, false, true)
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
state []byte
|
state []byte
|
||||||
storage []byte
|
storage []byte
|
||||||
|
|
@ -562,8 +565,7 @@ func dbDumpTrie(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage))
|
id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage))
|
||||||
|
theTrie, err := trie.New(id, triedb)
|
||||||
theTrie, err := trie.New(id, trie.NewDatabase(db))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -657,7 +659,7 @@ func importLDBdata(ctx *cli.Context) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, false)
|
db := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
|
defer db.Close()
|
||||||
return utils.ImportLDBData(db, fName, int64(start), stop)
|
return utils.ImportLDBData(db, fName, int64(start), stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -766,7 +768,7 @@ func exportChaindata(ctx *cli.Context) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
return utils.ExportChaindata(ctx.Args().Get(1), kind, exporter(db), stop)
|
return utils.ExportChaindata(ctx.Args().Get(1), kind, exporter(db), stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -774,6 +776,7 @@ func showMetaData(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
ancients, err := db.Ancients()
|
ancients, err := db.Ancients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
185
cmd/geth/logging_test.go
Normal file
185
cmd/geth/logging_test.go
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
//go:build integrationtests
|
||||||
|
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/internal/reexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runSelf(args ...string) ([]byte, error) {
|
||||||
|
cmd := &exec.Cmd{
|
||||||
|
Path: reexec.Self(),
|
||||||
|
Args: append([]string{"geth-test"}, args...),
|
||||||
|
}
|
||||||
|
return cmd.CombinedOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
func split(input io.Reader) []string {
|
||||||
|
var output []string
|
||||||
|
scanner := bufio.NewScanner(input)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
for scanner.Scan() {
|
||||||
|
output = append(output, strings.TrimSpace(scanner.Text()))
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func censor(input string, start, end int) string {
|
||||||
|
if len(input) < end {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
return input[:start] + strings.Repeat("X", end-start) + input[end:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogging(t *testing.T) {
|
||||||
|
testConsoleLogging(t, "terminal", 6, 24)
|
||||||
|
testConsoleLogging(t, "logfmt", 2, 26)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConsoleLogging(t *testing.T, format string, tStart, tEnd int) {
|
||||||
|
haveB, err := runSelf("--log.format", format, "logtest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
readFile, err := os.Open(fmt.Sprintf("testdata/logging/logtest-%v.txt", format))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
wantLines := split(readFile)
|
||||||
|
haveLines := split(bytes.NewBuffer(haveB))
|
||||||
|
for i, want := range wantLines {
|
||||||
|
if i > len(haveLines)-1 {
|
||||||
|
t.Fatalf("format %v, line %d missing, want:%v", format, i, want)
|
||||||
|
}
|
||||||
|
have := haveLines[i]
|
||||||
|
for strings.Contains(have, "Unknown config environment variable") {
|
||||||
|
// This can happen on CI runs. Drop it.
|
||||||
|
haveLines = append(haveLines[:i], haveLines[i+1:]...)
|
||||||
|
have = haveLines[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Black out the timestamp
|
||||||
|
have = censor(have, tStart, tEnd)
|
||||||
|
want = censor(want, tStart, tEnd)
|
||||||
|
if have != want {
|
||||||
|
t.Logf(nicediff([]byte(have), []byte(want)))
|
||||||
|
t.Fatalf("format %v, line %d\nhave %v\nwant %v", format, i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(haveLines) != len(wantLines) {
|
||||||
|
t.Errorf("format %v, want %d lines, have %d", format, len(haveLines), len(wantLines))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVmodule(t *testing.T) {
|
||||||
|
checkOutput := func(level int, want, wantNot string) {
|
||||||
|
t.Helper()
|
||||||
|
output, err := runSelf("--log.format", "terminal", "--verbosity=0", "--log.vmodule", fmt.Sprintf("logtestcmd_active.go=%d", level), "logtest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(want) > 0 && !strings.Contains(string(output), want) { // trace should be present at 5
|
||||||
|
t.Errorf("failed to find expected string ('%s') in output", want)
|
||||||
|
}
|
||||||
|
if len(wantNot) > 0 && strings.Contains(string(output), wantNot) { // trace should be present at 5
|
||||||
|
t.Errorf("string ('%s') should not be present in output", wantNot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkOutput(5, "log at level trace", "") // trace should be present at 5
|
||||||
|
checkOutput(4, "log at level debug", "log at level trace") // debug should be present at 4, but trace should be missing
|
||||||
|
checkOutput(3, "log at level info", "log at level debug") // info should be present at 3, but debug should be missing
|
||||||
|
checkOutput(2, "log at level warn", "log at level info") // warn should be present at 2, but info should be missing
|
||||||
|
checkOutput(1, "log at level error", "log at level warn") // error should be present at 1, but warn should be missing
|
||||||
|
}
|
||||||
|
|
||||||
|
func nicediff(have, want []byte) string {
|
||||||
|
var i = 0
|
||||||
|
for ; i < len(have) && i < len(want); i++ {
|
||||||
|
if want[i] != have[i] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var end = i + 40
|
||||||
|
var start = i - 50
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
var h, w string
|
||||||
|
if end < len(have) {
|
||||||
|
h = string(have[start:end])
|
||||||
|
} else {
|
||||||
|
h = string(have[start:])
|
||||||
|
}
|
||||||
|
if end < len(want) {
|
||||||
|
w = string(want[start:end])
|
||||||
|
} else {
|
||||||
|
w = string(want[start:])
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("have vs want:\n%q\n%q\n", h, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileOut(t *testing.T) {
|
||||||
|
var (
|
||||||
|
have, want []byte
|
||||||
|
err error
|
||||||
|
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
||||||
|
)
|
||||||
|
t.Cleanup(func() { os.Remove(path) })
|
||||||
|
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if have, err = os.ReadFile(path); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(have, want) {
|
||||||
|
// show an intelligent diff
|
||||||
|
t.Logf(nicediff(have, want))
|
||||||
|
t.Errorf("file content wrong")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRotatingFileOut(t *testing.T) {
|
||||||
|
var (
|
||||||
|
have, want []byte
|
||||||
|
err error
|
||||||
|
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
||||||
|
)
|
||||||
|
t.Cleanup(func() { os.Remove(path) })
|
||||||
|
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if have, err = os.ReadFile(path); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(have, want) {
|
||||||
|
// show an intelligent diff
|
||||||
|
t.Logf(nicediff(have, want))
|
||||||
|
t.Errorf("file content wrong")
|
||||||
|
}
|
||||||
|
}
|
||||||
159
cmd/geth/logtestcmd_active.go
Normal file
159
cmd/geth/logtestcmd_active.go
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
//go:build integrationtests
|
||||||
|
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var logTestCommand = &cli.Command{
|
||||||
|
Action: logTest,
|
||||||
|
Name: "logtest",
|
||||||
|
Usage: "Print some log messages",
|
||||||
|
ArgsUsage: " ",
|
||||||
|
Description: `
|
||||||
|
This command is only meant for testing.
|
||||||
|
`}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
log.ResetGlobalState()
|
||||||
|
{ // 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"
|
||||||
|
bc, _ := new(big.Int).SetString("11122233344455567899900", 10) // "11,122,233,344,455,567,899,900"
|
||||||
|
bd, _ := new(big.Int).SetString("-11122233344455567899900", 10) // "-11,122,233,344,455,567,899,900"
|
||||||
|
log.Info("big.Int", "111,222,333,444,555,678,999", ba)
|
||||||
|
log.Info("-big.Int", "-111,222,333,444,555,678,999", bb)
|
||||||
|
log.Info("big.Int", "11,122,233,344,455,567,899,900", bc)
|
||||||
|
log.Info("-big.Int", "-11,122,233,344,455,567,899,900", bd)
|
||||||
|
}
|
||||||
|
{ //uint256
|
||||||
|
ua, _ := uint256.FromDecimal("111222333444555678999")
|
||||||
|
ub, _ := uint256.FromDecimal("11122233344455567899900")
|
||||||
|
log.Info("uint256", "111,222,333,444,555,678,999", ua)
|
||||||
|
log.Info("uint256", "11,122,233,344,455,567,899,900", ub)
|
||||||
|
}
|
||||||
|
{ // int64
|
||||||
|
log.Info("int64", "1,000,000", int64(1000000))
|
||||||
|
log.Info("int64", "-1,000,000", int64(-1000000))
|
||||||
|
log.Info("int64", "9,223,372,036,854,775,807", int64(math.MaxInt64))
|
||||||
|
log.Info("int64", "-9,223,372,036,854,775,808", int64(math.MinInt64))
|
||||||
|
}
|
||||||
|
{ // uint64
|
||||||
|
log.Info("uint64", "1,000,000", uint64(1000000))
|
||||||
|
log.Info("uint64", "18,446,744,073,709,551,615", uint64(math.MaxUint64))
|
||||||
|
}
|
||||||
|
{ // Special characters
|
||||||
|
log.Info("Special chars in value", "key", "special \r\n\t chars")
|
||||||
|
log.Info("Special chars in key", "special \n\t chars", "value")
|
||||||
|
|
||||||
|
log.Info("nospace", "nospace", "nospace")
|
||||||
|
log.Info("with space", "with nospace", "with nospace")
|
||||||
|
|
||||||
|
log.Info("Bash escapes in value", "key", "\u001b[1G\u001b[K\u001b[1A")
|
||||||
|
log.Info("Bash escapes in key", "\u001b[1G\u001b[K\u001b[1A", "value")
|
||||||
|
|
||||||
|
log.Info("Bash escapes in message \u001b[1G\u001b[K\u001b[1A end", "key", "value")
|
||||||
|
|
||||||
|
colored := fmt.Sprintf("\u001B[%dmColored\u001B[0m[", 35)
|
||||||
|
log.Info(colored, colored, colored)
|
||||||
|
}
|
||||||
|
{ // Custom Stringer() - type
|
||||||
|
log.Info("Custom Stringer value", "2562047h47m16.854s", common.PrettyDuration(time.Duration(9223372036854775807)))
|
||||||
|
}
|
||||||
|
{ // Lazy eval
|
||||||
|
log.Info("Lazy evaluation of value", "key", log.Lazy{Fn: func() interface{} { return "lazy value" }})
|
||||||
|
}
|
||||||
|
{ // Multi-line message
|
||||||
|
log.Info("A message with wonky \U0001F4A9 characters")
|
||||||
|
log.Info("A multiline message \nINFO [10-18|14:11:31.106] with wonky characters \U0001F4A9")
|
||||||
|
log.Info("A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above")
|
||||||
|
}
|
||||||
|
{ // Miscellaneous json-quirks
|
||||||
|
// This will check if the json output uses strings or json-booleans to represent bool values
|
||||||
|
log.Info("boolean", "true", true, "false", false)
|
||||||
|
// Handling of duplicate keys.
|
||||||
|
// This is actually ill-handled by the current handler: the format.go
|
||||||
|
// uses a global 'fieldPadding' map and mixes up the two keys. If 'alpha'
|
||||||
|
// is shorter than beta, it sometimes causes erroneous padding -- and what's more
|
||||||
|
// it causes _different_ padding in multi-handler context, e.g. both file-
|
||||||
|
// and console output, making the two mismatch.
|
||||||
|
log.Info("repeated-key 1", "foo", "alpha", "foo", "beta")
|
||||||
|
log.Info("repeated-key 2", "xx", "short", "xx", "longer")
|
||||||
|
}
|
||||||
|
{ // loglevels
|
||||||
|
log.Debug("log at level debug")
|
||||||
|
log.Trace("log at level trace")
|
||||||
|
log.Info("log at level info")
|
||||||
|
log.Warn("log at level warn")
|
||||||
|
log.Error("log at level error")
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// The current log formatter has a global map of paddings, storing the
|
||||||
|
// longest seen padding per key in a map. This results in a statefulness
|
||||||
|
// which has some odd side-effects. Demonstrated here:
|
||||||
|
log.Info("test", "bar", "short", "a", "aligned left")
|
||||||
|
log.Info("test", "bar", "a long message", "a", 1)
|
||||||
|
log.Info("test", "bar", "short", "a", "aligned right")
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// This sequence of logs should be output with alignment, so each field becoems a column.
|
||||||
|
log.Info("The following logs should align so that the key-fields make 5 columns")
|
||||||
|
log.Info("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 1_123_123, "other", "first")
|
||||||
|
log.Info("Inserted new block", "number", 1, "hash", common.HexToHash("0x1235"), "txs", 2, "gas", 1_123, "other", "second")
|
||||||
|
log.Info("Inserted known block", "number", 99, "hash", common.HexToHash("0x12322"), "txs", 10, "gas", 1, "other", "third")
|
||||||
|
log.Warn("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 99, "other", "fourth")
|
||||||
|
}
|
||||||
|
{ // Various types of nil
|
||||||
|
type customStruct struct {
|
||||||
|
A string
|
||||||
|
B *uint64
|
||||||
|
}
|
||||||
|
log.Info("(*big.Int)(nil)", "<nil>", (*big.Int)(nil))
|
||||||
|
log.Info("(*uint256.Int)(nil)", "<nil>", (*uint256.Int)(nil))
|
||||||
|
log.Info("(fmt.Stringer)(nil)", "res", (fmt.Stringer)(nil))
|
||||||
|
log.Info("nil-concrete-stringer", "res", (*time.Time)(nil))
|
||||||
|
|
||||||
|
log.Info("error(nil) ", "res", error(nil))
|
||||||
|
log.Info("nil-concrete-error", "res", (*customError)(nil))
|
||||||
|
|
||||||
|
log.Info("nil-custom-struct", "res", (*customStruct)(nil))
|
||||||
|
log.Info("raw nil", "res", nil)
|
||||||
|
log.Info("(*uint64)(nil)", "res", (*uint64)(nil))
|
||||||
|
}
|
||||||
|
{ // Logging with 'reserved' keys
|
||||||
|
log.Info("Using keys 't', 'lvl', 'time', 'level' and 'msg'", "t", "t", "time", "time", "lvl", "lvl", "level", "level", "msg", "msg")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// customError is a type which implements error
|
||||||
|
type customError struct{}
|
||||||
|
|
||||||
|
func (c *customError) Error() string { return "" }
|
||||||
23
cmd/geth/logtestcmd_inactive.go
Normal file
23
cmd/geth/logtestcmd_inactive.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
//go:build !integrationtests
|
||||||
|
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
var logTestCommand *cli.Command
|
||||||
|
|
@ -94,6 +94,8 @@ var (
|
||||||
utils.GCModeFlag,
|
utils.GCModeFlag,
|
||||||
utils.SnapshotFlag,
|
utils.SnapshotFlag,
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
|
utils.TransactionHistoryFlag,
|
||||||
|
utils.StateHistoryFlag,
|
||||||
utils.LightServeFlag,
|
utils.LightServeFlag,
|
||||||
utils.LightIngressFlag,
|
utils.LightIngressFlag,
|
||||||
utils.LightEgressFlag,
|
utils.LightEgressFlag,
|
||||||
|
|
@ -152,7 +154,7 @@ var (
|
||||||
utils.GpoMaxGasPriceFlag,
|
utils.GpoMaxGasPriceFlag,
|
||||||
utils.GpoIgnoreGasPriceFlag,
|
utils.GpoIgnoreGasPriceFlag,
|
||||||
configFileFlag,
|
configFileFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags)
|
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
utils.HTTPEnabledFlag,
|
utils.HTTPEnabledFlag,
|
||||||
|
|
@ -242,6 +244,9 @@ func init() {
|
||||||
// See verkle.go
|
// See verkle.go
|
||||||
verkleCommand,
|
verkleCommand,
|
||||||
}
|
}
|
||||||
|
if logTestCommand != nil {
|
||||||
|
app.Commands = append(app.Commands, logTestCommand)
|
||||||
|
}
|
||||||
sort.Sort(cli.CommandsByName(app.Commands))
|
sort.Sort(cli.CommandsByName(app.Commands))
|
||||||
|
|
||||||
app.Flags = flags.Merge(
|
app.Flags = flags.Merge(
|
||||||
|
|
@ -252,11 +257,16 @@ func init() {
|
||||||
metricsFlags,
|
metricsFlags,
|
||||||
utils.BorFlags,
|
utils.BorFlags,
|
||||||
)
|
)
|
||||||
|
flags.AutoEnvVars(app.Flags, "GETH")
|
||||||
|
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
|
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
|
||||||
flags.MigrateGlobalFlags(ctx)
|
flags.MigrateGlobalFlags(ctx)
|
||||||
return debug.Setup(ctx)
|
if err := debug.Setup(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
flags.CheckEnvVars(ctx, app.Flags, "GETH")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
app.After = func(ctx *cli.Context) error {
|
app.After = func(ctx *cli.Context) error {
|
||||||
debug.Exit()
|
debug.Exit()
|
||||||
|
|
@ -316,7 +326,8 @@ func prepare(ctx *cli.Context) {
|
||||||
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
||||||
if ctx.String(utils.SyncModeFlag.Name) != light && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
if ctx.String(utils.SyncModeFlag.Name) != light && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||||
// Make sure we're not on any supported preconfigured testnet either
|
// Make sure we're not on any supported preconfigured testnet either
|
||||||
if !ctx.IsSet(utils.SepoliaFlag.Name) &&
|
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
|
||||||
|
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
||||||
!ctx.IsSet(utils.GoerliFlag.Name) &&
|
!ctx.IsSet(utils.GoerliFlag.Name) &&
|
||||||
!ctx.IsSet(utils.MumbaiFlag.Name) &&
|
!ctx.IsSet(utils.MumbaiFlag.Name) &&
|
||||||
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
"github.com/ethereum/go-ethereum/internal/cmdtest"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/reexec"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ var (
|
||||||
Action: pruneState,
|
Action: pruneState,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.BloomFilterSizeFlag,
|
utils.BloomFilterSizeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot prune-state <state-root>
|
geth snapshot prune-state <state-root>
|
||||||
will prune historical state data with the help of the state snapshot.
|
will prune historical state data with the help of the state snapshot.
|
||||||
|
|
@ -62,10 +62,7 @@ two version states are available: genesis and the specific one.
|
||||||
|
|
||||||
The default pruning target is the HEAD-127 state.
|
The default pruning target is the HEAD-127 state.
|
||||||
|
|
||||||
WARNING: It's necessary to delete the trie clean cache after the pruning.
|
WARNING: it's only supported in hash mode(--state.scheme=hash)".
|
||||||
If you specify another directory for the trie clean cache via "--cache.trie.journal"
|
|
||||||
during the use of Geth, please also specify it here for correct deletion. Otherwise
|
|
||||||
the trie clean cache with default directory will be deleted.
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -73,7 +70,7 @@ the trie clean cache with default directory will be deleted.
|
||||||
Usage: "Recalculate state hash based on the snapshot for verification",
|
Usage: "Recalculate state hash based on the snapshot for verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: verifyState,
|
Action: verifyState,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot verify-state <state-root>
|
geth snapshot verify-state <state-root>
|
||||||
will traverse the whole accounts and storages set based on the specified
|
will traverse the whole accounts and storages set based on the specified
|
||||||
|
|
@ -86,7 +83,7 @@ In other words, this command does the snapshot to trie conversion.
|
||||||
Usage: "Check that there is no 'dangling' snap storage",
|
Usage: "Check that there is no 'dangling' snap storage",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: checkDanglingStorage,
|
Action: checkDanglingStorage,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
||||||
data, and verifies that all snapshot storage data has a corresponding account.
|
data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
|
|
@ -97,7 +94,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
Usage: "Check all snapshot layers for the a specific account",
|
Usage: "Check all snapshot layers for the a specific account",
|
||||||
ArgsUsage: "<address | hash>",
|
ArgsUsage: "<address | hash>",
|
||||||
Action: checkAccount,
|
Action: checkAccount,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
||||||
information about the specified address.
|
information about the specified address.
|
||||||
|
|
@ -108,7 +105,7 @@ information about the specified address.
|
||||||
Usage: "Traverse the state with given root hash and perform quick verification",
|
Usage: "Traverse the state with given root hash and perform quick verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: traverseState,
|
Action: traverseState,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-state <state-root>
|
geth snapshot traverse-state <state-root>
|
||||||
will traverse the whole state from the given state root and will abort if any
|
will traverse the whole state from the given state root and will abort if any
|
||||||
|
|
@ -123,7 +120,7 @@ It's also usable without snapshot enabled.
|
||||||
Usage: "Traverse the state with given root hash and perform detailed verification",
|
Usage: "Traverse the state with given root hash and perform detailed verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: traverseRawState,
|
Action: traverseRawState,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-rawstate <state-root>
|
geth snapshot traverse-rawstate <state-root>
|
||||||
will traverse the whole state from the given root and will abort if any referenced
|
will traverse the whole state from the given root and will abort if any referenced
|
||||||
|
|
@ -144,7 +141,7 @@ It's also usable without snapshot enabled.
|
||||||
utils.ExcludeStorageFlag,
|
utils.ExcludeStorageFlag,
|
||||||
utils.StartKeyFlag,
|
utils.StartKeyFlag,
|
||||||
utils.DumpLimitFlag,
|
utils.DumpLimitFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
This command is semantically equivalent to 'geth dump', but uses the snapshots
|
This command is semantically equivalent to 'geth dump', but uses the snapshots
|
||||||
as the backend data source, making this command a lot faster.
|
as the backend data source, making this command a lot faster.
|
||||||
|
|
@ -166,6 +163,9 @@ func pruneState(ctx *cli.Context) error {
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
|
if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme {
|
||||||
|
log.Crit("Offline pruning is not required for path scheme")
|
||||||
|
}
|
||||||
prunerconfig := pruner.Config{
|
prunerconfig := pruner.Config{
|
||||||
Datadir: stack.ResolvePath(""),
|
Datadir: stack.ResolvePath(""),
|
||||||
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
|
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
|
||||||
|
|
@ -211,15 +211,16 @@ func verifyState(ctx *cli.Context) error {
|
||||||
log.Error("Failed to load head block")
|
log.Error("Failed to load head block")
|
||||||
return errors.New("no head block")
|
return errors.New("no head block")
|
||||||
}
|
}
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
snapconfig := snapshot.Config{
|
snapConfig := snapshot.Config{
|
||||||
CacheSize: 256,
|
CacheSize: 256,
|
||||||
Recovery: false,
|
Recovery: false,
|
||||||
NoBuild: true,
|
NoBuild: true,
|
||||||
AsyncBuild: false,
|
AsyncBuild: false,
|
||||||
}
|
}
|
||||||
|
snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root())
|
||||||
snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb), headBlock.Root())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to open snapshot tree", "err", err)
|
log.Error("Failed to open snapshot tree", "err", err)
|
||||||
return err
|
return err
|
||||||
|
|
@ -255,7 +256,9 @@ func checkDanglingStorage(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
return snapshot.CheckDanglingStorage(utils.MakeChainDatabase(ctx, stack, true))
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer db.Close()
|
||||||
|
return snapshot.CheckDanglingStorage(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// traverseState is a helper function used for pruning verification.
|
// traverseState is a helper function used for pruning verification.
|
||||||
|
|
@ -266,6 +269,10 @@ func traverseState(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer chaindb.Close()
|
||||||
|
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||||
if headBlock == nil {
|
if headBlock == nil {
|
||||||
|
|
@ -295,9 +302,6 @@ func traverseState(ctx *cli.Context) error {
|
||||||
root = headBlock.Root()
|
root = headBlock.Root()
|
||||||
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
|
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
|
||||||
}
|
}
|
||||||
|
|
||||||
triedb := trie.NewDatabase(chaindb)
|
|
||||||
|
|
||||||
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
|
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to open trie", "root", root, "err", err)
|
log.Error("Failed to open trie", "root", root, "err", err)
|
||||||
|
|
@ -342,6 +346,11 @@ func traverseState(ctx *cli.Context) error {
|
||||||
storageIter := trie.NewIterator(storageIt)
|
storageIter := trie.NewIterator(storageIt)
|
||||||
for storageIter.Next() {
|
for storageIter.Next() {
|
||||||
slots += 1
|
slots += 1
|
||||||
|
|
||||||
|
if time.Since(lastReport) > time.Second*8 {
|
||||||
|
log.Info("Traversing state", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
lastReport = time.Now()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if storageIter.Err != nil {
|
if storageIter.Err != nil {
|
||||||
|
|
@ -384,6 +393,10 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer chaindb.Close()
|
||||||
|
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||||
if headBlock == nil {
|
if headBlock == nil {
|
||||||
|
|
@ -413,9 +426,6 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
root = headBlock.Root()
|
root = headBlock.Root()
|
||||||
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
|
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
|
||||||
}
|
}
|
||||||
|
|
||||||
triedb := trie.NewDatabase(chaindb)
|
|
||||||
|
|
||||||
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
|
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to open trie", "root", root, "err", err)
|
log.Error("Failed to open trie", "root", root, "err", err)
|
||||||
|
|
@ -437,6 +447,11 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
log.Error("Failed to open iterator", "root", root, "err", err)
|
log.Error("Failed to open iterator", "root", root, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
reader, err := triedb.Reader(root)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("State is non-existent", "root", root)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
for accIter.Next(true) {
|
for accIter.Next(true) {
|
||||||
nodes += 1
|
nodes += 1
|
||||||
node := accIter.Hash()
|
node := accIter.Hash()
|
||||||
|
|
@ -444,7 +459,7 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
// Check the present for non-empty hash node(embedded node doesn't
|
// Check the present for non-empty hash node(embedded node doesn't
|
||||||
// have their own hash).
|
// have their own hash).
|
||||||
if node != (common.Hash{}) {
|
if node != (common.Hash{}) {
|
||||||
blob := rawdb.ReadLegacyTrieNode(chaindb, node)
|
blob, _ := reader.Node(common.Hash{}, accIter.Path(), node)
|
||||||
if len(blob) == 0 {
|
if len(blob) == 0 {
|
||||||
log.Error("Missing trie node(account)", "hash", node)
|
log.Error("Missing trie node(account)", "hash", node)
|
||||||
return errors.New("missing account")
|
return errors.New("missing account")
|
||||||
|
|
@ -490,7 +505,7 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
// Check the presence for non-empty hash node(embedded node doesn't
|
// Check the presence for non-empty hash node(embedded node doesn't
|
||||||
// have their own hash).
|
// have their own hash).
|
||||||
if node != (common.Hash{}) {
|
if node != (common.Hash{}) {
|
||||||
blob := rawdb.ReadLegacyTrieNode(chaindb, node)
|
blob, _ := reader.Node(common.BytesToHash(accIter.LeafKey()), storageIter.Path(), node)
|
||||||
if len(blob) == 0 {
|
if len(blob) == 0 {
|
||||||
log.Error("Missing trie node(storage)", "hash", node)
|
log.Error("Missing trie node(storage)", "hash", node)
|
||||||
return errors.New("missing storage")
|
return errors.New("missing storage")
|
||||||
|
|
@ -509,6 +524,10 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
if storageIter.Leaf() {
|
if storageIter.Leaf() {
|
||||||
slots += 1
|
slots += 1
|
||||||
}
|
}
|
||||||
|
if time.Since(lastReport) > time.Second*8 {
|
||||||
|
log.Info("Traversing state", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
lastReport = time.Now()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if storageIter.Error() != nil {
|
if storageIter.Error() != nil {
|
||||||
|
|
@ -560,6 +579,8 @@ func dumpState(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
triedb := utils.MakeTrieDatabase(ctx, db, false, true)
|
||||||
|
defer triedb.Close()
|
||||||
|
|
||||||
snapConfig := snapshot.Config{
|
snapConfig := snapshot.Config{
|
||||||
CacheSize: 256,
|
CacheSize: 256,
|
||||||
|
|
@ -567,8 +588,7 @@ func dumpState(ctx *cli.Context) error {
|
||||||
NoBuild: true,
|
NoBuild: true,
|
||||||
AsyncBuild: false,
|
AsyncBuild: false,
|
||||||
}
|
}
|
||||||
|
snaptree, err := snapshot.New(snapConfig, db, triedb, root)
|
||||||
snaptree, err := snapshot.New(snapConfig, db, trie.NewDatabase(db), root)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
cmd/geth/testdata/logging/logtest-json.txt
vendored
Normal file
49
cmd/geth/testdata/logging/logtest-json.txt
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{"111,222,333,444,555,678,999":"111222333444555678999","lvl":"info","msg":"big.Int","t":"2023-11-09T08:33:19.464383209+01:00"}
|
||||||
|
{"-111,222,333,444,555,678,999":"-111222333444555678999","lvl":"info","msg":"-big.Int","t":"2023-11-09T08:33:19.46455928+01:00"}
|
||||||
|
{"11,122,233,344,455,567,899,900":"11122233344455567899900","lvl":"info","msg":"big.Int","t":"2023-11-09T08:33:19.464582073+01:00"}
|
||||||
|
{"-11,122,233,344,455,567,899,900":"-11122233344455567899900","lvl":"info","msg":"-big.Int","t":"2023-11-09T08:33:19.464594846+01:00"}
|
||||||
|
{"111,222,333,444,555,678,999":"0x607851afc94ca2517","lvl":"info","msg":"uint256","t":"2023-11-09T08:33:19.464607873+01:00"}
|
||||||
|
{"11,122,233,344,455,567,899,900":"0x25aeffe8aaa1ef67cfc","lvl":"info","msg":"uint256","t":"2023-11-09T08:33:19.464694639+01:00"}
|
||||||
|
{"1,000,000":1000000,"lvl":"info","msg":"int64","t":"2023-11-09T08:33:19.464708835+01:00"}
|
||||||
|
{"-1,000,000":-1000000,"lvl":"info","msg":"int64","t":"2023-11-09T08:33:19.464725054+01:00"}
|
||||||
|
{"9,223,372,036,854,775,807":9223372036854775807,"lvl":"info","msg":"int64","t":"2023-11-09T08:33:19.464735773+01:00"}
|
||||||
|
{"-9,223,372,036,854,775,808":-9223372036854775808,"lvl":"info","msg":"int64","t":"2023-11-09T08:33:19.464744532+01:00"}
|
||||||
|
{"1,000,000":1000000,"lvl":"info","msg":"uint64","t":"2023-11-09T08:33:19.464752807+01:00"}
|
||||||
|
{"18,446,744,073,709,551,615":18446744073709551615,"lvl":"info","msg":"uint64","t":"2023-11-09T08:33:19.464779296+01:00"}
|
||||||
|
{"key":"special \r\n\t chars","lvl":"info","msg":"Special chars in value","t":"2023-11-09T08:33:19.464794181+01:00"}
|
||||||
|
{"lvl":"info","msg":"Special chars in key","special \n\t chars":"value","t":"2023-11-09T08:33:19.464827197+01:00"}
|
||||||
|
{"lvl":"info","msg":"nospace","nospace":"nospace","t":"2023-11-09T08:33:19.464841118+01:00"}
|
||||||
|
{"lvl":"info","msg":"with space","t":"2023-11-09T08:33:19.464862818+01:00","with nospace":"with nospace"}
|
||||||
|
{"key":"\u001b[1G\u001b[K\u001b[1A","lvl":"info","msg":"Bash escapes in value","t":"2023-11-09T08:33:19.464876802+01:00"}
|
||||||
|
{"\u001b[1G\u001b[K\u001b[1A":"value","lvl":"info","msg":"Bash escapes in key","t":"2023-11-09T08:33:19.464885416+01:00"}
|
||||||
|
{"key":"value","lvl":"info","msg":"Bash escapes in message \u001b[1G\u001b[K\u001b[1A end","t":"2023-11-09T08:33:19.464906946+01:00"}
|
||||||
|
{"\u001b[35mColored\u001b[0m[":"\u001b[35mColored\u001b[0m[","lvl":"info","msg":"\u001b[35mColored\u001b[0m[","t":"2023-11-09T08:33:19.464921455+01:00"}
|
||||||
|
{"2562047h47m16.854s":"2562047h47m16.854s","lvl":"info","msg":"Custom Stringer value","t":"2023-11-09T08:33:19.464943893+01:00"}
|
||||||
|
{"key":"lazy value","lvl":"info","msg":"Lazy evaluation of value","t":"2023-11-09T08:33:19.465013552+01:00"}
|
||||||
|
{"lvl":"info","msg":"A message with wonky 💩 characters","t":"2023-11-09T08:33:19.465069437+01:00"}
|
||||||
|
{"lvl":"info","msg":"A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩","t":"2023-11-09T08:33:19.465083053+01:00"}
|
||||||
|
{"lvl":"info","msg":"A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above","t":"2023-11-09T08:33:19.465104289+01:00"}
|
||||||
|
{"false":"false","lvl":"info","msg":"boolean","t":"2023-11-09T08:33:19.465117185+01:00","true":"true"}
|
||||||
|
{"foo":"beta","lvl":"info","msg":"repeated-key 1","t":"2023-11-09T08:33:19.465143425+01:00"}
|
||||||
|
{"lvl":"info","msg":"repeated-key 2","t":"2023-11-09T08:33:19.465156323+01:00","xx":"longer"}
|
||||||
|
{"lvl":"info","msg":"log at level info","t":"2023-11-09T08:33:19.465193158+01:00"}
|
||||||
|
{"lvl":"warn","msg":"log at level warn","t":"2023-11-09T08:33:19.465228964+01:00"}
|
||||||
|
{"lvl":"eror","msg":"log at level error","t":"2023-11-09T08:33:19.465240352+01:00"}
|
||||||
|
{"a":"aligned left","bar":"short","lvl":"info","msg":"test","t":"2023-11-09T08:33:19.465247226+01:00"}
|
||||||
|
{"a":1,"bar":"a long message","lvl":"info","msg":"test","t":"2023-11-09T08:33:19.465269028+01:00"}
|
||||||
|
{"a":"aligned right","bar":"short","lvl":"info","msg":"test","t":"2023-11-09T08:33:19.465313611+01:00"}
|
||||||
|
{"lvl":"info","msg":"The following logs should align so that the key-fields make 5 columns","t":"2023-11-09T08:33:19.465328188+01:00"}
|
||||||
|
{"gas":1123123,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","lvl":"info","msg":"Inserted known block","number":1012,"other":"first","t":"2023-11-09T08:33:19.465350507+01:00","txs":200}
|
||||||
|
{"gas":1123,"hash":"0x0000000000000000000000000000000000000000000000000000000000001235","lvl":"info","msg":"Inserted new block","number":1,"other":"second","t":"2023-11-09T08:33:19.465387952+01:00","txs":2}
|
||||||
|
{"gas":1,"hash":"0x0000000000000000000000000000000000000000000000000000000000012322","lvl":"info","msg":"Inserted known block","number":99,"other":"third","t":"2023-11-09T08:33:19.465406687+01:00","txs":10}
|
||||||
|
{"gas":99,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","lvl":"warn","msg":"Inserted known block","number":1012,"other":"fourth","t":"2023-11-09T08:33:19.465433025+01:00","txs":200}
|
||||||
|
{"\u003cnil\u003e":"\u003cnil\u003e","lvl":"info","msg":"(*big.Int)(nil)","t":"2023-11-09T08:33:19.465450283+01:00"}
|
||||||
|
{"\u003cnil\u003e":"nil","lvl":"info","msg":"(*uint256.Int)(nil)","t":"2023-11-09T08:33:19.465472953+01:00"}
|
||||||
|
{"lvl":"info","msg":"(fmt.Stringer)(nil)","res":"\u003cnil\u003e","t":"2023-11-09T08:33:19.465538633+01:00"}
|
||||||
|
{"lvl":"info","msg":"nil-concrete-stringer","res":"nil","t":"2023-11-09T08:33:19.465552355+01:00"}
|
||||||
|
{"lvl":"info","msg":"error(nil) ","res":"\u003cnil\u003e","t":"2023-11-09T08:33:19.465601029+01:00"}
|
||||||
|
{"lvl":"info","msg":"nil-concrete-error","res":"","t":"2023-11-09T08:33:19.46561622+01:00"}
|
||||||
|
{"lvl":"info","msg":"nil-custom-struct","res":"\u003cnil\u003e","t":"2023-11-09T08:33:19.465638888+01:00"}
|
||||||
|
{"lvl":"info","msg":"raw nil","res":"\u003cnil\u003e","t":"2023-11-09T08:33:19.465673664+01:00"}
|
||||||
|
{"lvl":"info","msg":"(*uint64)(nil)","res":"\u003cnil\u003e","t":"2023-11-09T08:33:19.465700264+01:00"}
|
||||||
|
{"level":"level","lvl":"lvl","msg":"msg","t":"t","time":"time"}
|
||||||
49
cmd/geth/testdata/logging/logtest-logfmt.txt
vendored
Normal file
49
cmd/geth/testdata/logging/logtest-logfmt.txt
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=big.Int 111,222,333,444,555,678,999=111,222,333,444,555,678,999
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=-big.Int -111,222,333,444,555,678,999=-111,222,333,444,555,678,999
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=big.Int 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=-big.Int -11,122,233,344,455,567,899,900=-11,122,233,344,455,567,899,900
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=uint256 111,222,333,444,555,678,999=111,222,333,444,555,678,999
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=uint256 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=int64 1,000,000=1,000,000
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=int64 -1,000,000=-1,000,000
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=int64 9,223,372,036,854,775,807=9,223,372,036,854,775,807
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=int64 -9,223,372,036,854,775,808=-9,223,372,036,854,775,808
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=uint64 1,000,000=1,000,000
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=uint64 18,446,744,073,709,551,615=18,446,744,073,709,551,615
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Special chars in value" key="special \r\n\t chars"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Special chars in key" "special \n\t chars"=value
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=nospace nospace=nospace
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="with space" "with nospace"="with nospace"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Bash escapes in value" key="\x1b[1G\x1b[K\x1b[1A"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Bash escapes in key" "\x1b[1G\x1b[K\x1b[1A"=value
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m["
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Custom Stringer value" 2562047h47m16.854s=2562047h47m16.854s
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Lazy evaluation of value" key="lazy value"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="A message with wonky 💩 characters"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=boolean true=true false=false
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="repeated-key 1" foo=alpha foo=beta
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="repeated-key 2" xx=short xx=longer
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="log at level info"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=warn msg="log at level warn"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=eror msg="log at level error"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=test bar=short a="aligned left"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=test bar="a long message" a=1
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=test bar=short a="aligned right"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="The following logs should align so that the key-fields make 5 columns"
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=1,123,123 other=first
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Inserted new block" number=1 hash=0x0000000000000000000000000000000000000000000000000000000000001235 txs=2 gas=1123 other=second
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Inserted known block" number=99 hash=0x0000000000000000000000000000000000000000000000000000000000012322 txs=10 gas=1 other=third
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=warn msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=99 other=fourth
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=(*big.Int)(nil) <nil>=<nil>
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=(*uint256.Int)(nil) <nil>=<nil>
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=(fmt.Stringer)(nil) res=nil
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=nil-concrete-stringer res=nil
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="error(nil) " res=nil
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=nil-concrete-error res=
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=nil-custom-struct res=<nil>
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="raw nil" res=nil
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg=(*uint64)(nil) res=<nil>
|
||||||
|
t=xxxxxxxxxxxxxxxxxxxxxxxx lvl=info msg="Using keys 't', 'lvl', 'time', 'level' and 'msg'" t=t time=time lvl=lvl level=level msg=msg
|
||||||
50
cmd/geth/testdata/logging/logtest-terminal.txt
vendored
Normal file
50
cmd/geth/testdata/logging/logtest-terminal.txt
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] big.Int 111,222,333,444,555,678,999=111,222,333,444,555,678,999
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] -big.Int -111,222,333,444,555,678,999=-111,222,333,444,555,678,999
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] big.Int 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] -big.Int -11,122,233,344,455,567,899,900=-11,122,233,344,455,567,899,900
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] uint256 111,222,333,444,555,678,999=111,222,333,444,555,678,999
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] uint256 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] int64 1,000,000=1,000,000
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] int64 -1,000,000=-1,000,000
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] int64 9,223,372,036,854,775,807=9,223,372,036,854,775,807
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] int64 -9,223,372,036,854,775,808=-9,223,372,036,854,775,808
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] uint64 1,000,000=1,000,000
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] uint64 18,446,744,073,709,551,615=18,446,744,073,709,551,615
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Special chars in value key="special \r\n\t chars"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Special chars in key "special \n\t chars"=value
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] nospace nospace=nospace
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] with space "with nospace"="with nospace"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Bash escapes in value key="\x1b[1G\x1b[K\x1b[1A"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Bash escapes in key "\x1b[1G\x1b[K\x1b[1A"=value
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] "Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] "\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m["
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Custom Stringer value 2562047h47m16.854s=2562047h47m16.854s
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Lazy evaluation of value key="lazy value"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] "A message with wonky 💩 characters"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] "A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] A multiline message
|
||||||
|
LALA [XXZXXZXXZXXZXXZXXX] Actually part of message above
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] boolean true=true false=false
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] repeated-key 1 foo=alpha foo=beta
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] repeated-key 2 xx=short xx=longer
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] log at level info
|
||||||
|
WARN [XX-XX|XX:XX:XX.XXX] log at level warn
|
||||||
|
ERROR[XX-XX|XX:XX:XX.XXX] log at level error
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] test bar=short a="aligned left"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] test bar="a long message" a=1
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] test bar=short a="aligned right"
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] The following logs should align so that the key-fields make 5 columns
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Inserted known block number=1012 hash=000000..001234 txs=200 gas=1,123,123 other=first
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Inserted new block number=1 hash=000000..001235 txs=2 gas=1123 other=second
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Inserted known block number=99 hash=000000..012322 txs=10 gas=1 other=third
|
||||||
|
WARN [XX-XX|XX:XX:XX.XXX] Inserted known block number=1012 hash=000000..001234 txs=200 gas=99 other=fourth
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] (*big.Int)(nil) <nil>=<nil>
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] (*uint256.Int)(nil) <nil>=<nil>
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] (fmt.Stringer)(nil) res=nil
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] nil-concrete-stringer res=nil
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] error(nil) res=nil
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] nil-concrete-error res=
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] nil-custom-struct res=<nil>
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] raw nil res=nil
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] (*uint64)(nil) res=<nil>
|
||||||
|
INFO [XX-XX|XX:XX:XX.XXX] Using keys 't', 'lvl', 'time', 'level' and 'msg' t=t time=time lvl=lvl level=level msg=msg
|
||||||
4
cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig
vendored
Normal file
4
cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
untrusted comment: signature from minisign secret key
|
||||||
|
RUQkliYstQBOKLK05Sy5f3bVRMBqJT26ABo6Vbp3BNJAVjejoqYCu4GWE/+7qcDfHBqYIniDCbFIUvYEnOHxV6vZ93wO1xJWDQw=
|
||||||
|
trusted comment: timestamp:1693986492 file:data.json hashed
|
||||||
|
6Fdw2H+W1ZXK7QXSF77Z5AWC7+AEFAfDmTSxNGylU5HLT1AuSJQmxslj+VjtUBamYCvOuET7plbXza942AlWDw==
|
||||||
|
|
@ -46,7 +46,7 @@ var (
|
||||||
Usage: "verify the conversion of a MPT into a verkle tree",
|
Usage: "verify the conversion of a MPT into a verkle tree",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: verifyVerkle,
|
Action: verifyVerkle,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth verkle verify <state-root>
|
geth verkle verify <state-root>
|
||||||
This command takes a root commitment and attempts to rebuild the tree.
|
This command takes a root commitment and attempts to rebuild the tree.
|
||||||
|
|
@ -57,7 +57,7 @@ This command takes a root commitment and attempts to rebuild the tree.
|
||||||
Usage: "Dump a verkle tree to a DOT file",
|
Usage: "Dump a verkle tree to a DOT file",
|
||||||
ArgsUsage: "<root> <key1> [<key 2> ...]",
|
ArgsUsage: "<root> <key1> [<key 2> ...]",
|
||||||
Action: expandVerkle,
|
Action: expandVerkle,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth verkle dump <state-root> <key 1> [<key 2> ...]
|
geth verkle dump <state-root> <key 1> [<key 2> ...]
|
||||||
This command will produce a dot file representing the tree, rooted at <root>.
|
This command will produce a dot file representing the tree, rooted at <root>.
|
||||||
|
|
@ -118,6 +118,7 @@ func verifyVerkle(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer chaindb.Close()
|
||||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||||
|
|
||||||
if headBlock == nil {
|
if headBlock == nil {
|
||||||
|
|
@ -174,7 +175,7 @@ func expandVerkle(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
|
defer chaindb.Close()
|
||||||
var (
|
var (
|
||||||
rootC common.Hash
|
rootC common.Hash
|
||||||
keylist [][]byte
|
keylist [][]byte
|
||||||
|
|
|
||||||
|
|
@ -30,17 +30,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVerification(t *testing.T) {
|
func TestVerification(t *testing.T) {
|
||||||
// Signatures generated with `minisign`
|
// Signatures generated with `minisign`. Legacy format, not pre-hashed file.
|
||||||
t.Run("minisig", func(t *testing.T) {
|
t.Run("minisig-legacy", func(t *testing.T) {
|
||||||
// For this test, the pubkey is in testdata/minisign.pub
|
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
||||||
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
||||||
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
||||||
testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
|
testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
|
||||||
})
|
})
|
||||||
|
t.Run("minisig-new", func(t *testing.T) {
|
||||||
|
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
||||||
|
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
||||||
|
// `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig`
|
||||||
|
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
||||||
|
testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/")
|
||||||
|
})
|
||||||
// Signatures generated with `signify-openbsd`
|
// Signatures generated with `signify-openbsd`
|
||||||
t.Run("signify-openbsd", func(t *testing.T) {
|
t.Run("signify-openbsd", func(t *testing.T) {
|
||||||
t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
|
t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
|
||||||
// For this test, the pubkey is in testdata/signifykey.pub
|
// For this test, the pubkey is in testdata/vcheck/signifykey.pub
|
||||||
// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
|
// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
|
||||||
pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
|
pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
|
||||||
testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
|
testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
|
||||||
|
|
@ -58,7 +65,9 @@ func testVerification(t *testing.T, pubkey, sigdir string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
if len(files) == 0 {
|
||||||
|
t.Fatal("Missing tests")
|
||||||
|
}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
sig, err := os.ReadFile(filepath.Join(sigdir, f.Name()))
|
sig, err := os.ReadFile(filepath.Join(sigdir, f.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
@ -43,16 +42,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
ethcatalyst "github.com/ethereum/go-ethereum/eth/catalyst"
|
"github.com/ethereum/go-ethereum/eth/catalyst"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
|
|
@ -76,8 +73,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"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"
|
||||||
|
pcsclite "github.com/gballet/go-libpcsclite"
|
||||||
|
gopsutil "github.com/shirou/gopsutil/mem"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// These are all the command line flags we support.
|
// These are all the command line flags we support.
|
||||||
|
|
@ -134,7 +136,7 @@ var (
|
||||||
}
|
}
|
||||||
NetworkIdFlag = &cli.Uint64Flag{
|
NetworkIdFlag = &cli.Uint64Flag{
|
||||||
Name: "networkid",
|
Name: "networkid",
|
||||||
Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia instead)",
|
Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia, --holesky instead)",
|
||||||
Value: ethconfig.Defaults.NetworkId,
|
Value: ethconfig.Defaults.NetworkId,
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -227,30 +229,12 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultSyncMode = ethconfig.Defaults.SyncMode
|
defaultSyncMode = ethconfig.Defaults.SyncMode
|
||||||
SyncModeFlag = &flags.TextMarshalerFlag{
|
SnapshotFlag = &cli.BoolFlag{
|
||||||
Name: "syncmode",
|
|
||||||
Usage: `Blockchain sync mode ("snap", "full" or "light")`,
|
|
||||||
Value: &defaultSyncMode,
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
GCModeFlag = &cli.StringFlag{
|
|
||||||
Name: "gcmode",
|
|
||||||
Usage: `Blockchain garbage collection mode ("full", "archive")`,
|
|
||||||
Value: "full",
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
SnapshotFlag = &cli.BoolFlag{
|
|
||||||
Name: "snapshot",
|
Name: "snapshot",
|
||||||
Usage: `Enables snapshot-database mode (default = enable)`,
|
Usage: `Enables snapshot-database mode (default = enable)`,
|
||||||
Value: true,
|
Value: true,
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
TxLookupLimitFlag = &cli.Uint64Flag{
|
|
||||||
Name: "txlookuplimit",
|
|
||||||
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
|
|
||||||
Value: ethconfig.Defaults.TxLookupLimit,
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
LightKDFFlag = &cli.BoolFlag{
|
LightKDFFlag = &cli.BoolFlag{
|
||||||
Name: "lightkdf",
|
Name: "lightkdf",
|
||||||
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
|
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
|
||||||
|
|
@ -277,6 +261,35 @@ var (
|
||||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||||
|
Name: "syncmode",
|
||||||
|
Usage: `Blockchain sync mode ("snap", "full" or "light")`,
|
||||||
|
Value: &defaultSyncMode,
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
GCModeFlag = &cli.StringFlag{
|
||||||
|
Name: "gcmode",
|
||||||
|
Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`,
|
||||||
|
Value: "full",
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
StateSchemeFlag = &cli.StringFlag{
|
||||||
|
Name: "state.scheme",
|
||||||
|
Usage: "Scheme to use for storing ethereum state ('hash' or 'path')",
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
StateHistoryFlag = &cli.Uint64Flag{
|
||||||
|
Name: "history.state",
|
||||||
|
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)",
|
||||||
|
Value: ethconfig.Defaults.StateHistory,
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
TransactionHistoryFlag = &cli.Uint64Flag{
|
||||||
|
Name: "history.transactions",
|
||||||
|
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
|
||||||
|
Value: ethconfig.Defaults.TransactionHistory,
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
// Light server and client settings
|
// Light server and client settings
|
||||||
LightServeFlag = &cli.IntFlag{
|
LightServeFlag = &cli.IntFlag{
|
||||||
Name: "light.serve",
|
Name: "light.serve",
|
||||||
|
|
@ -615,9 +628,9 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// MISC settings
|
// MISC settings
|
||||||
SyncTargetFlag = &cli.PathFlag{
|
SyncTargetFlag = &cli.StringFlag{
|
||||||
Name: "synctarget",
|
Name: "synctarget",
|
||||||
Usage: `File for containing the hex-encoded block-rlp as sync target(dev feature)`,
|
Usage: `Hash of the block to full sync to (dev testing feature)`,
|
||||||
TakesFile: true,
|
TakesFile: true,
|
||||||
Category: flags.MiscCategory,
|
Category: flags.MiscCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -976,25 +989,22 @@ var (
|
||||||
TestnetFlags = []cli.Flag{
|
TestnetFlags = []cli.Flag{
|
||||||
GoerliFlag,
|
GoerliFlag,
|
||||||
SepoliaFlag,
|
SepoliaFlag,
|
||||||
|
HoleskyFlag,
|
||||||
}
|
}
|
||||||
// NetworkFlags is the flag group of all built-in supported networks.
|
// NetworkFlags is the flag group of all built-in supported networks.
|
||||||
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
|
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
|
||||||
|
|
||||||
// DatabasePathFlags is the flag group of all database path flags.
|
// DatabaseFlags is the flag group of all database flags.
|
||||||
DatabasePathFlags = []cli.Flag{
|
DatabaseFlags = []cli.Flag{
|
||||||
DataDirFlag,
|
DataDirFlag,
|
||||||
AncientFlag,
|
AncientFlag,
|
||||||
RemoteDBFlag,
|
RemoteDBFlag,
|
||||||
|
DBEngineFlag,
|
||||||
|
StateSchemeFlag,
|
||||||
HttpHeaderFlag,
|
HttpHeaderFlag,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
if rawdb.PebbleEnabled {
|
|
||||||
DatabasePathFlags = append(DatabasePathFlags, DBEngineFlag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeDataDir retrieves the currently requested data directory, terminating
|
// MakeDataDir retrieves the currently requested data directory, terminating
|
||||||
// if none (or the empty string) is specified. If the node is starting a testnet,
|
// if none (or the empty string) is specified. If the node is starting a testnet,
|
||||||
// then a subdirectory of the specified datadir will be used.
|
// then a subdirectory of the specified datadir will be used.
|
||||||
|
|
@ -1007,7 +1017,6 @@ func MakeDataDir(ctx *cli.Context) string {
|
||||||
if ctx.Bool(SepoliaFlag.Name) {
|
if ctx.Bool(SepoliaFlag.Name) {
|
||||||
return filepath.Join(path, "sepolia")
|
return filepath.Join(path, "sepolia")
|
||||||
}
|
}
|
||||||
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1018,7 +1027,7 @@ func MakeDataDir(ctx *cli.Context) string {
|
||||||
|
|
||||||
// setNodeKey creates a node key from set command line flags, either loading it
|
// setNodeKey creates a node key from set command line flags, either loading it
|
||||||
// from a file or as a specified hex value. If neither flags were provided, this
|
// from a file or as a specified hex value. If neither flags were provided, this
|
||||||
// method returns nil and an emphemeral key is to be generated.
|
// method returns nil and an ephemeral key is to be generated.
|
||||||
func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
|
func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
var (
|
var (
|
||||||
hex = ctx.String(NodeKeyHexFlag.Name)
|
hex = ctx.String(NodeKeyHexFlag.Name)
|
||||||
|
|
@ -1054,36 +1063,45 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
|
||||||
|
|
||||||
// setBootstrapNodes creates a list of bootstrap nodes from the command line
|
// setBootstrapNodes creates a list of bootstrap nodes from the command line
|
||||||
// flags, reverting to pre-configured ones if none have been specified.
|
// flags, reverting to pre-configured ones if none have been specified.
|
||||||
|
// Priority order for bootnodes configuration:
|
||||||
|
//
|
||||||
|
// 1. --bootnodes flag
|
||||||
|
// 2. Config file
|
||||||
|
// 3. Network preset flags (e.g. --goerli)
|
||||||
|
// 4. default to mainnet nodes
|
||||||
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls := params.MainnetBootnodes
|
urls := params.MainnetBootnodes
|
||||||
|
if ctx.IsSet(BootnodesFlag.Name) {
|
||||||
switch {
|
|
||||||
case ctx.IsSet(BootnodesFlag.Name):
|
|
||||||
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
|
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
} else {
|
||||||
urls = params.SepoliaBootnodes
|
if cfg.BootstrapNodes != nil {
|
||||||
case ctx.Bool(GoerliFlag.Name):
|
return // Already set by config file, don't apply defaults.
|
||||||
urls = params.GoerliBootnodes
|
}
|
||||||
|
switch {
|
||||||
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
|
urls = params.HoleskyBootnodes
|
||||||
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
|
urls = params.SepoliaBootnodes
|
||||||
|
case ctx.Bool(GoerliFlag.Name):
|
||||||
|
urls = params.GoerliBootnodes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
||||||
|
}
|
||||||
|
|
||||||
// don't apply defaults if BootstrapNodes is already set
|
func mustParseBootnodes(urls []string) []*enode.Node {
|
||||||
if cfg.BootstrapNodes != nil {
|
nodes := make([]*enode.Node, 0, len(urls))
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
|
|
||||||
|
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
if url != "" {
|
if url != "" {
|
||||||
node, err := enode.Parse(enode.ValidSchemes, url)
|
node, err := enode.Parse(enode.ValidSchemes, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
|
log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
|
||||||
continue
|
return nil
|
||||||
}
|
}
|
||||||
|
nodes = append(nodes, node)
|
||||||
cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
|
// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
|
||||||
|
|
@ -1557,6 +1575,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
|
||||||
case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
||||||
|
case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1739,20 +1759,11 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
|
||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags
|
// Avoid conflicting network flags
|
||||||
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag)
|
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag)
|
||||||
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
|
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
|
||||||
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
|
|
||||||
// nolint:goconst
|
// Set configurations from CLI flags
|
||||||
if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
|
|
||||||
_ = ctx.Set(TxLookupLimitFlag.Name, "0")
|
|
||||||
log.Warn("Disable transaction unindexing for archive node")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
|
|
||||||
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
|
|
||||||
}
|
|
||||||
|
|
||||||
setEtherbase(ctx, cfg)
|
setEtherbase(ctx, cfg)
|
||||||
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
|
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
|
||||||
setTxPool(ctx, &cfg.TxPool)
|
setTxPool(ctx, &cfg.TxPool)
|
||||||
|
|
@ -1782,7 +1793,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
|
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
|
||||||
godebug.SetGCPercent(int(gogc))
|
godebug.SetGCPercent(int(gogc))
|
||||||
|
|
||||||
if ctx.IsSet(SyncModeFlag.Name) {
|
if ctx.IsSet(SyncTargetFlag.Name) {
|
||||||
|
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
|
||||||
|
} else if ctx.IsSet(SyncModeFlag.Name) {
|
||||||
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
|
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1820,9 +1833,30 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
|
|
||||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
log.Info("Enabling recording of key preimages since archive mode is used")
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(StateHistoryFlag.Name) {
|
||||||
if ctx.IsSet(TxLookupLimitFlag.Name) {
|
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
|
||||||
cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name)
|
}
|
||||||
|
if ctx.IsSet(StateSchemeFlag.Name) {
|
||||||
|
cfg.StateScheme = ctx.String(StateSchemeFlag.Name)
|
||||||
|
}
|
||||||
|
// Parse transaction history flag, if user is still using legacy config
|
||||||
|
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
|
||||||
|
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
|
||||||
|
log.Warn("The config option 'TxLookupLimit' is deprecated and will be removed, please use 'TransactionHistory'")
|
||||||
|
cfg.TransactionHistory = cfg.TxLookupLimit
|
||||||
|
}
|
||||||
|
if ctx.IsSet(TransactionHistoryFlag.Name) {
|
||||||
|
cfg.TransactionHistory = ctx.Uint64(TransactionHistoryFlag.Name)
|
||||||
|
} else if ctx.IsSet(TxLookupLimitFlag.Name) {
|
||||||
|
log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions")
|
||||||
|
cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
|
||||||
|
cfg.TransactionHistory = 0
|
||||||
|
log.Warn("Disabled transaction unindexing for archive node")
|
||||||
|
}
|
||||||
|
if ctx.IsSet(LightServeFlag.Name) && cfg.TransactionHistory != 0 {
|
||||||
|
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||||
|
|
@ -1896,6 +1930,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
|
|
||||||
cfg.Genesis = core.DefaultGenesisBlock()
|
cfg.Genesis = core.DefaultGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
||||||
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
|
cfg.NetworkId = 17000
|
||||||
|
}
|
||||||
|
cfg.Genesis = core.DefaultHoleskyGenesisBlock()
|
||||||
|
SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash)
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = 11155111
|
cfg.NetworkId = 11155111
|
||||||
|
|
@ -1965,15 +2005,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Create a new developer genesis block or reuse existing one
|
// Create a new developer genesis block or reuse existing one
|
||||||
cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
|
cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
|
||||||
if ctx.IsSet(DataDirFlag.Name) {
|
if ctx.IsSet(DataDirFlag.Name) {
|
||||||
// If datadir doesn't exist we need to open db in write-mode
|
chaindb := tryMakeReadOnlyDatabase(ctx, stack)
|
||||||
// so leveldb can create files.
|
|
||||||
readonly := true
|
|
||||||
if !common.FileExist(stack.ResolvePath("chaindata")) {
|
|
||||||
readonly = false
|
|
||||||
}
|
|
||||||
// Check if we have an already initialized chain and fall back to
|
|
||||||
// that if so. Otherwise we need to generate a new genesis spec.
|
|
||||||
chaindb := MakeChainDatabase(ctx, stack, readonly)
|
|
||||||
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
|
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
|
||||||
cfg.Genesis = nil // fallback to db content
|
cfg.Genesis = nil // fallback to db content
|
||||||
}
|
}
|
||||||
|
|
@ -2078,26 +2110,9 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterFullSyncTester adds the full-sync tester service into node.
|
// RegisterFullSyncTester adds the full-sync tester service into node.
|
||||||
func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, path string) {
|
func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash) {
|
||||||
blob, err := os.ReadFile(path)
|
catalyst.RegisterFullSyncTester(stack, eth, target)
|
||||||
if err != nil {
|
log.Info("Registered full-sync tester", "hash", target)
|
||||||
Fatalf("Failed to read block file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rlpBlob, err := hexutil.Decode(string(bytes.TrimRight(blob, "\r\n")))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
Fatalf("Failed to decode block blob: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var block types.Block
|
|
||||||
|
|
||||||
if err := rlp.DecodeBytes(rlpBlob, &block); err != nil {
|
|
||||||
Fatalf("Failed to decode block: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = ethcatalyst.RegisterFullSyncTester(stack, eth, &block)
|
|
||||||
log.Info("Registered full-sync tester", "number", block.NumberU64(), "hash", block.Hash())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupMetrics(ctx *cli.Context) {
|
func SetupMetrics(ctx *cli.Context) {
|
||||||
|
|
@ -2178,12 +2193,11 @@ func SplitTagsFlag(tagsFlag string) map[string]string {
|
||||||
return tagsMap
|
return tagsMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
|
// MakeChainDatabase opens a database using the flags passed to the client and will hard crash if it fails.
|
||||||
func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
|
func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
|
||||||
var (
|
var (
|
||||||
cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
||||||
handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
|
handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
|
||||||
|
|
||||||
err error
|
err error
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
|
|
||||||
|
|
@ -2213,13 +2227,16 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
|
||||||
return chainDb
|
return chainDb
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveExtraDBConfig(ctx *cli.Context) rawdb.ExtraDBConfig {
|
// tryMakeReadOnlyDatabase try to open the chain database in read-only mode,
|
||||||
return rawdb.ExtraDBConfig{
|
// or fallback to write mode if the database is not initialized.
|
||||||
LevelDBCompactionTableSize: ctx.Uint64(LevelDbCompactionTableSizeFlag.Name),
|
func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
|
||||||
LevelDBCompactionTableSizeMultiplier: ctx.Float64(LevelDbCompactionTableSizeMultiplierFlag.Name),
|
// If the database doesn't exist we need to open it in write-mode to allow
|
||||||
LevelDBCompactionTotalSize: ctx.Uint64(LevelDbCompactionTotalSizeFlag.Name),
|
// the engine to create files.
|
||||||
LevelDBCompactionTotalSizeMultiplier: ctx.Float64(LevelDbCompactionTotalSizeMultiplierFlag.Name),
|
readonly := true
|
||||||
|
if rawdb.PreexistingDatabase(stack.ResolvePath("chaindata")) == "" {
|
||||||
|
readonly = false
|
||||||
}
|
}
|
||||||
|
return MakeChainDatabase(ctx, stack, readonly)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsNetworkPreset(ctx *cli.Context) bool {
|
func IsNetworkPreset(ctx *cli.Context) bool {
|
||||||
|
|
@ -2247,8 +2264,7 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
|
||||||
var opts []rpc.ClientOption
|
var opts []rpc.ClientOption
|
||||||
|
|
||||||
if len(headers) > 0 {
|
if len(headers) > 0 {
|
||||||
var customHeaders = make(http.Header)
|
customHeaders := make(http.Header)
|
||||||
|
|
||||||
for _, h := range headers {
|
for _, h := range headers {
|
||||||
kv := strings.Split(h, ":")
|
kv := strings.Split(h, ":")
|
||||||
if len(kv) != 2 {
|
if len(kv) != 2 {
|
||||||
|
|
@ -2270,6 +2286,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(MainnetFlag.Name):
|
case ctx.Bool(MainnetFlag.Name):
|
||||||
genesis = core.DefaultGenesisBlock()
|
genesis = core.DefaultGenesisBlock()
|
||||||
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
|
genesis = core.DefaultHoleskyGenesisBlock()
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
genesis = core.DefaultSepoliaGenesisBlock()
|
genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
case ctx.Bool(GoerliFlag.Name):
|
case ctx.Bool(GoerliFlag.Name):
|
||||||
|
|
@ -2311,7 +2329,10 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
||||||
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
|
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
|
||||||
}
|
}
|
||||||
|
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb)
|
||||||
|
if err != nil {
|
||||||
|
Fatalf("%v", err)
|
||||||
|
}
|
||||||
cache := &core.CacheConfig{
|
cache := &core.CacheConfig{
|
||||||
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
|
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
|
||||||
TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
|
TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
|
||||||
|
|
@ -2320,6 +2341,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
|
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
|
||||||
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
|
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
|
||||||
Preimages: ctx.Bool(CachePreimagesFlag.Name),
|
Preimages: ctx.Bool(CachePreimagesFlag.Name),
|
||||||
|
StateScheme: scheme,
|
||||||
|
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
||||||
}
|
}
|
||||||
if cache.TrieDirtyDisabled && !cache.Preimages {
|
if cache.TrieDirtyDisabled && !cache.Preimages {
|
||||||
cache.Preimages = true
|
cache.Preimages = true
|
||||||
|
|
@ -2370,3 +2393,27 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
|
||||||
|
|
||||||
return preloads
|
return preloads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
||||||
|
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database {
|
||||||
|
config := &trie.Config{
|
||||||
|
Preimages: preimage,
|
||||||
|
}
|
||||||
|
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk)
|
||||||
|
if err != nil {
|
||||||
|
Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
if scheme == rawdb.HashScheme {
|
||||||
|
// Read-only mode is not implemented in hash mode,
|
||||||
|
// ignore the parameter silently. TODO(rjl493456442)
|
||||||
|
// please config it if read mode is implemented.
|
||||||
|
config.HashDB = hashdb.Defaults
|
||||||
|
return trie.NewDatabase(disk, config)
|
||||||
|
}
|
||||||
|
if readOnly {
|
||||||
|
config.PathDB = pathdb.ReadOnly
|
||||||
|
} else {
|
||||||
|
config.PathDB = pathdb.Defaults
|
||||||
|
}
|
||||||
|
return trie.NewDatabase(disk, config)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ package utils
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ShowDeprecated = &cli.Command{
|
var ShowDeprecated = &cli.Command{
|
||||||
|
|
@ -38,6 +38,7 @@ var DeprecatedFlags = []cli.Flag{
|
||||||
CacheTrieJournalFlag,
|
CacheTrieJournalFlag,
|
||||||
CacheTrieRejournalFlag,
|
CacheTrieRejournalFlag,
|
||||||
LegacyDiscoveryV5Flag,
|
LegacyDiscoveryV5Flag,
|
||||||
|
TxLookupLimitFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -69,6 +70,13 @@ var (
|
||||||
Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)",
|
Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)",
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
|
// Deprecated August 2023
|
||||||
|
TxLookupLimitFlag = &cli.Uint64Flag{
|
||||||
|
Name: "txlookuplimit",
|
||||||
|
Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) (deprecated, use history.transactions instead)",
|
||||||
|
Value: ethconfig.Defaults.TransactionHistory,
|
||||||
|
Category: flags.DeprecatedCategory,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,12 @@ const (
|
||||||
var (
|
var (
|
||||||
hashT = reflect.TypeOf(Hash{})
|
hashT = reflect.TypeOf(Hash{})
|
||||||
addressT = reflect.TypeOf(Address{})
|
addressT = reflect.TypeOf(Address{})
|
||||||
|
|
||||||
|
// MaxAddress represents the maximum possible address value.
|
||||||
|
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")
|
||||||
|
|
||||||
|
// MaxHash represents the maximum possible hash value.
|
||||||
|
MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||||
|
|
@ -258,9 +264,6 @@ func (a Address) Cmp(other Address) int {
|
||||||
// Bytes gets the string representation of the underlying address.
|
// Bytes gets the string representation of the underlying address.
|
||||||
func (a Address) Bytes() []byte { return a[:] }
|
func (a Address) Bytes() []byte { return a[:] }
|
||||||
|
|
||||||
// Hash converts an address to a hash by left-padding it with zeros.
|
|
||||||
func (a Address) Hash() Hash { return BytesToHash(a[:]) }
|
|
||||||
|
|
||||||
// Big converts an address to a big integer.
|
// Big converts an address to a big integer.
|
||||||
func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
|
func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBytesConversion(t *testing.T) {
|
func TestBytesConversion(t *testing.T) {
|
||||||
|
|
@ -614,3 +615,14 @@ func TestAddressEIP55(t *testing.T) {
|
||||||
t.Fatal("Unexpected address after unmarshal")
|
t.Fatal("Unexpected address after unmarshal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrettyDuration(b *testing.B) {
|
||||||
|
var x = PrettyDuration(time.Duration(int64(1203123912312)))
|
||||||
|
b.Logf("Pre %s", time.Duration(x).String())
|
||||||
|
var a string
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
a = x.String()
|
||||||
|
}
|
||||||
|
b.Logf("Post %s", a)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -270,15 +270,21 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
||||||
if !shanghai && header.WithdrawalsHash != nil {
|
if !shanghai && header.WithdrawalsHash != nil {
|
||||||
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
|
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
|
||||||
}
|
}
|
||||||
// Verify the existence / non-existence of excessBlobGas
|
// Verify the existence / non-existence of cancun-specific header fields
|
||||||
cancun := chain.Config().IsCancun(header.Number)
|
cancun := chain.Config().IsCancun(header.Number, header.Time)
|
||||||
if !cancun && header.ExcessBlobGas != nil {
|
if !cancun {
|
||||||
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
switch {
|
||||||
}
|
case header.ExcessBlobGas != nil:
|
||||||
if !cancun && header.BlobGasUsed != nil {
|
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
||||||
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
case header.BlobGasUsed != nil:
|
||||||
}
|
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
||||||
if cancun {
|
case header.ParentBeaconRoot != nil:
|
||||||
|
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if header.ParentBeaconRoot == nil {
|
||||||
|
return errors.New("header is missing beaconRoot")
|
||||||
|
}
|
||||||
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
|
||||||
return errors.New("header is missing blobGasUsed")
|
return errors.New("header is missing blobGasUsed")
|
||||||
}
|
}
|
||||||
// Verify that the blob gas used remains within reasonable limits.
|
// Verify that the blob gas used remains within reasonable limits.
|
||||||
if *header.BlobGasUsed > params.BlobTxMaxBlobGasPerBlock {
|
if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
|
||||||
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.BlobTxMaxBlobGasPerBlock)
|
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
|
||||||
}
|
}
|
||||||
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
|
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
|
||||||
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
|
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,14 @@ func TestCalcExcessBlobGas(t *testing.T) {
|
||||||
// The excess blob gas should decrease by however much the target was
|
// The excess blob gas should decrease by however much the target was
|
||||||
// under-shot, capped at zero.
|
// under-shot, capped at zero.
|
||||||
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
|
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
|
||||||
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxBlobGasPerBlob},
|
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob},
|
||||||
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, 0},
|
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)},
|
||||||
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
|
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for i, tt := range tests {
|
||||||
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
|
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
|
||||||
if result != tt.want {
|
if result != tt.want {
|
||||||
t.Errorf("excess blob gas mismatch: have %v, want %v", result, tt.want)
|
t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,9 +65,9 @@ func TestCalcBlobFee(t *testing.T) {
|
||||||
blobfee int64
|
blobfee int64
|
||||||
}{
|
}{
|
||||||
{0, 1},
|
{0, 1},
|
||||||
{1542706, 1},
|
{2314057, 1},
|
||||||
{1542707, 2},
|
{2314058, 2},
|
||||||
{10 * 1024 * 1024, 111},
|
{10 * 1024 * 1024, 23},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
have := CalcBlobFee(tt.excessBlobGas)
|
have := CalcBlobFee(tt.excessBlobGas)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package misc
|
package misc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -38,7 +37,7 @@ func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if headerGasLimit < params.MinGasLimit {
|
if headerGasLimit < params.MinGasLimit {
|
||||||
return errors.New("invalid gas limit below 5000")
|
return fmt.Errorf("invalid gas limit below %d", params.MinGasLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ type instructionIterator struct {
|
||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInstructionIterator create a new instruction iterator.
|
// NewInstructionIterator creates a new instruction iterator.
|
||||||
func NewInstructionIterator(code []byte) *instructionIterator {
|
func NewInstructionIterator(code []byte) *instructionIterator {
|
||||||
it := new(instructionIterator)
|
it := new(instructionIterator)
|
||||||
it.code = code
|
it.code = code
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
package asm
|
package asm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -30,7 +32,7 @@ import (
|
||||||
// and holds the tokens for the program.
|
// and holds the tokens for the program.
|
||||||
type Compiler struct {
|
type Compiler struct {
|
||||||
tokens []token
|
tokens []token
|
||||||
binary []interface{}
|
out []byte
|
||||||
|
|
||||||
labels map[string]int
|
labels map[string]int
|
||||||
|
|
||||||
|
|
@ -47,15 +49,13 @@ func NewCompiler(debug bool) *Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feed feeds tokens in to ch and are interpreted by
|
// Feed feeds tokens into ch and are interpreted by
|
||||||
// the compiler.
|
// the compiler.
|
||||||
//
|
//
|
||||||
// feed is the first pass in the compile stage as it
|
// feed is the first pass in the compile stage as it collects the used labels in the
|
||||||
// collects the used labels in the program and keeps a
|
// program and keeps a program counter which is used to determine the locations of the
|
||||||
// program counter which is used to determine the locations
|
// jump dests. The labels can than be used in the second stage to push labels and
|
||||||
// of the jump dests. The labels can than be used in the
|
// determine the right position.
|
||||||
// second stage to push labels and determine the right
|
|
||||||
// position.
|
|
||||||
func (c *Compiler) Feed(ch <-chan token) {
|
func (c *Compiler) Feed(ch <-chan token) {
|
||||||
var prev token
|
var prev token
|
||||||
|
|
||||||
|
|
@ -81,7 +81,6 @@ func (c *Compiler) Feed(ch <-chan token) {
|
||||||
c.pc++
|
c.pc++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.tokens = append(c.tokens, i)
|
c.tokens = append(c.tokens, i)
|
||||||
prev = i
|
prev = i
|
||||||
}
|
}
|
||||||
|
|
@ -91,12 +90,11 @@ func (c *Compiler) Feed(ch <-chan token) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile compiles the current tokens and returns a
|
// Compile compiles the current tokens and returns a binary string that can be interpreted
|
||||||
// binary string that can be interpreted by the EVM
|
// by the EVM and an error if it failed.
|
||||||
// and an error if it failed.
|
|
||||||
//
|
//
|
||||||
// compile is the second stage in the compile phase
|
// compile is the second stage in the compile phase which compiles the tokens to EVM
|
||||||
// which compiles the tokens to EVM instructions.
|
// instructions.
|
||||||
func (c *Compiler) Compile() (string, []error) {
|
func (c *Compiler) Compile() (string, []error) {
|
||||||
var errors []error
|
var errors []error
|
||||||
// continue looping over the tokens until
|
// continue looping over the tokens until
|
||||||
|
|
@ -108,18 +106,8 @@ func (c *Compiler) Compile() (string, []error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn the binary to hex
|
// turn the binary to hex
|
||||||
var bin strings.Builder
|
h := hex.EncodeToString(c.out)
|
||||||
|
return h, errors
|
||||||
for _, v := range c.binary {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case vm.OpCode:
|
|
||||||
bin.WriteString(fmt.Sprintf("%x", []byte{byte(v)}))
|
|
||||||
case []byte:
|
|
||||||
bin.WriteString(fmt.Sprintf("%x", v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bin.String(), errors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// next returns the next token and increments the
|
// next returns the next token and increments the
|
||||||
|
|
@ -162,90 +150,114 @@ func (c *Compiler) compileLine() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compileNumber compiles the number to bytes
|
// parseNumber compiles the number to bytes
|
||||||
func (c *Compiler) compileNumber(element token) {
|
func parseNumber(tok token) ([]byte, error) {
|
||||||
num := math.MustParseBig256(element.text).Bytes()
|
if tok.typ != number {
|
||||||
if len(num) == 0 {
|
panic("parseNumber of non-number token")
|
||||||
num = []byte{0}
|
|
||||||
}
|
}
|
||||||
|
num, ok := math.ParseBig256(tok.text)
|
||||||
c.pushBin(num)
|
if !ok {
|
||||||
|
return nil, errors.New("invalid number")
|
||||||
|
}
|
||||||
|
bytes := num.Bytes()
|
||||||
|
if len(bytes) == 0 {
|
||||||
|
bytes = []byte{0}
|
||||||
|
}
|
||||||
|
return bytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compileElement compiles the element (push & label or both)
|
// compileElement compiles the element (push & label or both)
|
||||||
// to a binary representation and may error if incorrect statements
|
// to a binary representation and may error if incorrect statements
|
||||||
// where fed.
|
// where fed.
|
||||||
func (c *Compiler) compileElement(element token) error {
|
func (c *Compiler) compileElement(element token) error {
|
||||||
// check for a jump. jumps must be read and compiled
|
switch {
|
||||||
// from right to left.
|
case isJump(element.text):
|
||||||
if isJump(element.text) {
|
return c.compileJump(element.text)
|
||||||
rvalue := c.next()
|
case isPush(element.text):
|
||||||
switch rvalue.typ {
|
return c.compilePush()
|
||||||
case number:
|
default:
|
||||||
// TODO figure out how to return the error properly
|
c.outputOpcode(toBinary(element.text))
|
||||||
c.compileNumber(rvalue)
|
|
||||||
case stringValue:
|
|
||||||
// strings are quoted, remove them.
|
|
||||||
c.pushBin(rvalue.text[1 : len(rvalue.text)-2])
|
|
||||||
case label:
|
|
||||||
c.pushBin(vm.PUSH4)
|
|
||||||
pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes()
|
|
||||||
pos = append(make([]byte, 4-len(pos)), pos...)
|
|
||||||
c.pushBin(pos)
|
|
||||||
case lineEnd:
|
|
||||||
c.pos--
|
|
||||||
default:
|
|
||||||
return compileErr(rvalue, rvalue.text, "number, string or label")
|
|
||||||
}
|
|
||||||
// push the operation
|
|
||||||
c.pushBin(toBinary(element.text))
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
} else if isPush(element.text) {
|
|
||||||
// handle pushes. pushes are read from left to right.
|
|
||||||
var value []byte
|
|
||||||
|
|
||||||
rvalue := c.next()
|
|
||||||
switch rvalue.typ {
|
|
||||||
case number:
|
|
||||||
value = math.MustParseBig256(rvalue.text).Bytes()
|
|
||||||
if len(value) == 0 {
|
|
||||||
value = []byte{0}
|
|
||||||
}
|
|
||||||
case stringValue:
|
|
||||||
value = []byte(rvalue.text[1 : len(rvalue.text)-1])
|
|
||||||
case label:
|
|
||||||
value = big.NewInt(int64(c.labels[rvalue.text])).Bytes()
|
|
||||||
value = append(make([]byte, 4-len(value)), value...)
|
|
||||||
default:
|
|
||||||
return compileErr(rvalue, rvalue.text, "number, string or label")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(value) > 32 {
|
|
||||||
return fmt.Errorf("%d type error: unsupported string or number with size > 32", rvalue.lineno)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.pushBin(vm.OpCode(int(vm.PUSH1) - 1 + len(value)))
|
|
||||||
c.pushBin(value)
|
|
||||||
} else {
|
|
||||||
c.pushBin(toBinary(element.text))
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) compileJump(jumpType string) error {
|
||||||
|
rvalue := c.next()
|
||||||
|
switch rvalue.typ {
|
||||||
|
case number:
|
||||||
|
numBytes, err := parseNumber(rvalue)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.outputBytes(numBytes)
|
||||||
|
|
||||||
|
case stringValue:
|
||||||
|
// strings are quoted, remove them.
|
||||||
|
str := rvalue.text[1 : len(rvalue.text)-2]
|
||||||
|
c.outputBytes([]byte(str))
|
||||||
|
|
||||||
|
case label:
|
||||||
|
c.outputOpcode(vm.PUSH4)
|
||||||
|
pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes()
|
||||||
|
pos = append(make([]byte, 4-len(pos)), pos...)
|
||||||
|
c.outputBytes(pos)
|
||||||
|
|
||||||
|
case lineEnd:
|
||||||
|
// push without argument is supported, it just takes the destination from the stack.
|
||||||
|
c.pos--
|
||||||
|
|
||||||
|
default:
|
||||||
|
return compileErr(rvalue, rvalue.text, "number, string or label")
|
||||||
|
}
|
||||||
|
// push the operation
|
||||||
|
c.outputOpcode(toBinary(jumpType))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) compilePush() error {
|
||||||
|
// handle pushes. pushes are read from left to right.
|
||||||
|
var value []byte
|
||||||
|
rvalue := c.next()
|
||||||
|
switch rvalue.typ {
|
||||||
|
case number:
|
||||||
|
value = math.MustParseBig256(rvalue.text).Bytes()
|
||||||
|
if len(value) == 0 {
|
||||||
|
value = []byte{0}
|
||||||
|
}
|
||||||
|
case stringValue:
|
||||||
|
value = []byte(rvalue.text[1 : len(rvalue.text)-1])
|
||||||
|
case label:
|
||||||
|
value = big.NewInt(int64(c.labels[rvalue.text])).Bytes()
|
||||||
|
value = append(make([]byte, 4-len(value)), value...)
|
||||||
|
default:
|
||||||
|
return compileErr(rvalue, rvalue.text, "number, string or label")
|
||||||
|
}
|
||||||
|
if len(value) > 32 {
|
||||||
|
return fmt.Errorf("%d: string or number size > 32 bytes", rvalue.lineno+1)
|
||||||
|
}
|
||||||
|
c.outputOpcode(vm.OpCode(int(vm.PUSH1) - 1 + len(value)))
|
||||||
|
c.outputBytes(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compileLabel pushes a jumpdest to the binary slice.
|
// compileLabel pushes a jumpdest to the binary slice.
|
||||||
func (c *Compiler) compileLabel() {
|
func (c *Compiler) compileLabel() {
|
||||||
c.pushBin(vm.JUMPDEST)
|
c.outputOpcode(vm.JUMPDEST)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushBin pushes the value v to the binary stack.
|
func (c *Compiler) outputOpcode(op vm.OpCode) {
|
||||||
func (c *Compiler) pushBin(v interface{}) {
|
|
||||||
if c.debug {
|
if c.debug {
|
||||||
fmt.Printf("%d: %v\n", len(c.binary), v)
|
fmt.Printf("%d: %v\n", len(c.out), op)
|
||||||
}
|
}
|
||||||
|
c.out = append(c.out, byte(op))
|
||||||
|
}
|
||||||
|
|
||||||
c.binary = append(c.binary, v)
|
// output pushes the value v to the binary stack.
|
||||||
|
func (c *Compiler) outputBytes(b []byte) {
|
||||||
|
if c.debug {
|
||||||
|
fmt.Printf("%d: %x\n", len(c.out), b)
|
||||||
|
}
|
||||||
|
c.out = append(c.out, b...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isPush returns whether the string op is either any of
|
// isPush returns whether the string op is either any of
|
||||||
|
|
@ -272,13 +284,13 @@ type compileError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err compileError) Error() string {
|
func (err compileError) Error() string {
|
||||||
return fmt.Sprintf("%d syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want)
|
return fmt.Sprintf("%d: syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileErr(c token, got, want string) error {
|
func compileErr(c token, got, want string) error {
|
||||||
return compileError{
|
return compileError{
|
||||||
got: got,
|
got: got,
|
||||||
want: want,
|
want: want,
|
||||||
lineno: c.lineno,
|
lineno: c.lineno + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,14 @@ func TestCompiler(t *testing.T) {
|
||||||
`,
|
`,
|
||||||
output: "6300000006565b",
|
output: "6300000006565b",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
JUMP @label
|
||||||
|
label: ;; comment
|
||||||
|
ADD ;; comment
|
||||||
|
`,
|
||||||
|
output: "6300000006565b01",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
ch := Lex([]byte(test.input), false)
|
ch := Lex([]byte(test.input), false)
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,16 @@ func TestLexer(t *testing.T) {
|
||||||
input: "@label123",
|
input: "@label123",
|
||||||
tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}},
|
tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}},
|
||||||
},
|
},
|
||||||
|
// Comment after label
|
||||||
|
{
|
||||||
|
input: "@label123 ;; comment",
|
||||||
|
tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}},
|
||||||
|
},
|
||||||
|
// Comment after instruction
|
||||||
|
{
|
||||||
|
input: "push 3 ;; comment\nadd",
|
||||||
|
tokens: []token{{typ: lineStart}, {typ: element, text: "push"}, {typ: number, text: "3"}, {typ: lineEnd, text: "\n"}, {typ: lineStart, lineno: 1}, {typ: element, lineno: 1, text: "add"}, {typ: eof, lineno: 1}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ type token struct {
|
||||||
// is able to parse and return.
|
// is able to parse and return.
|
||||||
type tokenType int
|
type tokenType int
|
||||||
|
|
||||||
|
//go:generate go run golang.org/x/tools/cmd/stringer -type tokenType
|
||||||
|
|
||||||
const (
|
const (
|
||||||
eof tokenType = iota // end of file
|
eof tokenType = iota // end of file
|
||||||
lineStart // emitted when a line starts
|
lineStart // emitted when a line starts
|
||||||
|
|
@ -52,32 +54,13 @@ const (
|
||||||
labelDef // label definition is emitted when a new label is found
|
labelDef // label definition is emitted when a new label is found
|
||||||
number // number is emitted when a number is found
|
number // number is emitted when a number is found
|
||||||
stringValue // stringValue is emitted when a string has been found
|
stringValue // stringValue is emitted when a string has been found
|
||||||
|
|
||||||
Numbers = "1234567890" // characters representing any decimal number
|
|
||||||
HexadecimalNumbers = Numbers + "aAbBcCdDeEfF" // characters representing any hexadecimal
|
|
||||||
Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// String implements stringer
|
const (
|
||||||
func (it tokenType) String() string {
|
decimalNumbers = "1234567890" // characters representing any decimal number
|
||||||
if int(it) > len(stringtokenTypes) {
|
hexNumbers = decimalNumbers + "aAbBcCdDeEfF" // characters representing any hexadecimal
|
||||||
return "invalid"
|
alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric
|
||||||
}
|
)
|
||||||
|
|
||||||
return stringtokenTypes[it]
|
|
||||||
}
|
|
||||||
|
|
||||||
var stringtokenTypes = []string{
|
|
||||||
eof: "EOF",
|
|
||||||
lineStart: "new line",
|
|
||||||
lineEnd: "end of line",
|
|
||||||
invalidStatement: "invalid statement",
|
|
||||||
element: "element",
|
|
||||||
label: "label",
|
|
||||||
labelDef: "label definition",
|
|
||||||
number: "number",
|
|
||||||
stringValue: "string",
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexer is the basic construct for parsing
|
// lexer is the basic construct for parsing
|
||||||
// source code and turning them in to tokens.
|
// source code and turning them in to tokens.
|
||||||
|
|
@ -207,7 +190,6 @@ func lexLine(l *lexer) stateFn {
|
||||||
l.ignore()
|
l.ignore()
|
||||||
|
|
||||||
l.lineno++
|
l.lineno++
|
||||||
|
|
||||||
l.emit(lineStart)
|
l.emit(lineStart)
|
||||||
case r == ';' && l.peek() == ';':
|
case r == ';' && l.peek() == ';':
|
||||||
return lexComment
|
return lexComment
|
||||||
|
|
@ -232,6 +214,7 @@ func lexLine(l *lexer) stateFn {
|
||||||
// of the line and discards the text.
|
// of the line and discards the text.
|
||||||
func lexComment(l *lexer) stateFn {
|
func lexComment(l *lexer) stateFn {
|
||||||
l.acceptRunUntil('\n')
|
l.acceptRunUntil('\n')
|
||||||
|
l.backup()
|
||||||
l.ignore()
|
l.ignore()
|
||||||
|
|
||||||
return lexLine
|
return lexLine
|
||||||
|
|
@ -241,7 +224,7 @@ func lexComment(l *lexer) stateFn {
|
||||||
// the lex text state function to advance the parsing
|
// the lex text state function to advance the parsing
|
||||||
// process.
|
// process.
|
||||||
func lexLabel(l *lexer) stateFn {
|
func lexLabel(l *lexer) stateFn {
|
||||||
l.acceptRun(Alpha + "_" + Numbers)
|
l.acceptRun(alpha + "_" + decimalNumbers)
|
||||||
|
|
||||||
l.emit(label)
|
l.emit(label)
|
||||||
|
|
||||||
|
|
@ -260,9 +243,9 @@ func lexInsideString(l *lexer) stateFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lexNumber(l *lexer) stateFn {
|
func lexNumber(l *lexer) stateFn {
|
||||||
acceptance := Numbers
|
acceptance := decimalNumbers
|
||||||
if l.accept("xX") {
|
if l.accept("xX") {
|
||||||
acceptance = HexadecimalNumbers
|
acceptance = hexNumbers
|
||||||
}
|
}
|
||||||
|
|
||||||
l.acceptRun(acceptance)
|
l.acceptRun(acceptance)
|
||||||
|
|
@ -273,7 +256,7 @@ func lexNumber(l *lexer) stateFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lexElement(l *lexer) stateFn {
|
func lexElement(l *lexer) stateFn {
|
||||||
l.acceptRun(Alpha + "_" + Numbers)
|
l.acceptRun(alpha + "_" + decimalNumbers)
|
||||||
|
|
||||||
if l.peek() == ':' {
|
if l.peek() == ':' {
|
||||||
l.emit(labelDef)
|
l.emit(labelDef)
|
||||||
|
|
|
||||||
31
core/asm/tokentype_string.go
Normal file
31
core/asm/tokentype_string.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Code generated by "stringer -type tokenType"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package asm
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[eof-0]
|
||||||
|
_ = x[lineStart-1]
|
||||||
|
_ = x[lineEnd-2]
|
||||||
|
_ = x[invalidStatement-3]
|
||||||
|
_ = x[element-4]
|
||||||
|
_ = x[label-5]
|
||||||
|
_ = x[labelDef-6]
|
||||||
|
_ = x[number-7]
|
||||||
|
_ = x[stringValue-8]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _tokenType_name = "eoflineStartlineEndinvalidStatementelementlabellabelDefnumberstringValue"
|
||||||
|
|
||||||
|
var _tokenType_index = [...]uint8{0, 3, 12, 19, 35, 42, 47, 55, 61, 72}
|
||||||
|
|
||||||
|
func (i tokenType) String() string {
|
||||||
|
if i < 0 || i >= tokenType(len(_tokenType_index)-1) {
|
||||||
|
return "tokenType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _tokenType_name[_tokenType_index[i]:_tokenType_index[i+1]]
|
||||||
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||||
toaddr := common.Address{}
|
toaddr := common.Address{}
|
||||||
data := make([]byte, nbytes)
|
data := make([]byte, nbytes)
|
||||||
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
||||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
signer := gen.Signer()
|
||||||
gasPrice := big.NewInt(0)
|
gasPrice := big.NewInt(0)
|
||||||
if gen.header.BaseFee != nil {
|
if gen.header.BaseFee != nil {
|
||||||
gasPrice = gen.header.BaseFee
|
gasPrice = gen.header.BaseFee
|
||||||
|
|
@ -132,7 +132,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
||||||
if gen.header.BaseFee != nil {
|
if gen.header.BaseFee != nil {
|
||||||
gasPrice = gen.header.BaseFee
|
gasPrice = gen.header.BaseFee
|
||||||
}
|
}
|
||||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
signer := gen.Signer()
|
||||||
for {
|
for {
|
||||||
gas -= params.TxGas
|
gas -= params.TxGas
|
||||||
if gas < params.TxGas {
|
if gas < params.TxGas {
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||||
return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash)
|
return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Withdrawals are present after the Shanghai fork.
|
// Withdrawals are present after the Shanghai fork.
|
||||||
if header.WithdrawalsHash != nil {
|
if header.WithdrawalsHash != nil {
|
||||||
// Withdrawals list must be present in body after Shanghai.
|
// Withdrawals list must be present in body after Shanghai.
|
||||||
|
|
@ -86,14 +87,23 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
// Withdrawals are not allowed prior to Shanghai fork
|
// Withdrawals are not allowed prior to Shanghai fork
|
||||||
return errors.New("withdrawals present in block body")
|
return errors.New("withdrawals present in block body")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blob transactions may be present after the Cancun fork.
|
// Blob transactions may be present after the Cancun fork.
|
||||||
var blobs int
|
var blobs int
|
||||||
for _, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// Count the number of blobs to validate against the header's blobGasUsed
|
// Count the number of blobs to validate against the header's blobGasUsed
|
||||||
blobs += len(tx.BlobHashes())
|
blobs += len(tx.BlobHashes())
|
||||||
|
|
||||||
|
// If the tx is a blob tx, it must NOT have a sidecar attached to be valid in a block.
|
||||||
|
if tx.BlobTxSidecar() != nil {
|
||||||
|
return fmt.Errorf("unexpected blob sidecar in transaction at index %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
// The individual checks for blob validity (version-check + not empty)
|
// The individual checks for blob validity (version-check + not empty)
|
||||||
// happens in the state_transition check.
|
// happens in StateTransition.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check blob gas usage.
|
||||||
if header.BlobGasUsed != nil {
|
if header.BlobGasUsed != nil {
|
||||||
if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
|
if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
|
||||||
return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob)
|
return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob)
|
||||||
|
|
@ -103,6 +113,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
return errors.New("data blobs present in block body")
|
return errors.New("data blobs present in block body")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ancestor block must be known.
|
||||||
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
|
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
|
||||||
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
|
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
|
||||||
return consensus.ErrUnknownAncestor
|
return consensus.ErrUnknownAncestor
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@ import (
|
||||||
|
|
||||||
// Tests that simple header verification works, for both good and bad blocks.
|
// Tests that simple header verification works, for both good and bad blocks.
|
||||||
func TestHeaderVerification(t *testing.T) {
|
func TestHeaderVerification(t *testing.T) {
|
||||||
|
testHeaderVerification(t, rawdb.HashScheme)
|
||||||
|
testHeaderVerification(t, rawdb.PathScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderVerification(t *testing.T, scheme string) {
|
||||||
// Create a simple chain to verify
|
// Create a simple chain to verify
|
||||||
var (
|
var (
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
gspec = &Genesis{Config: params.TestChainConfig}
|
||||||
|
|
@ -46,7 +51,7 @@ func TestHeaderVerification(t *testing.T) {
|
||||||
headers[i] = block.Header()
|
headers[i] = block.Header()
|
||||||
}
|
}
|
||||||
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
||||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
for i := 0; i < len(blocks); i++ {
|
for i := 0; i < len(blocks); i++ {
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -69,6 +71,8 @@ var (
|
||||||
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
||||||
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
|
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
|
||||||
|
|
||||||
|
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
||||||
|
|
||||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
||||||
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
||||||
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
|
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
|
||||||
|
|
@ -141,7 +145,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CacheConfig contains the configuration values for the trie database
|
// CacheConfig contains the configuration values for the trie database
|
||||||
// that's resident in a blockchain.
|
// and state snapshot these are resident in a blockchain.
|
||||||
type CacheConfig struct {
|
type CacheConfig struct {
|
||||||
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
||||||
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
|
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
|
||||||
|
|
@ -151,11 +155,31 @@ type CacheConfig struct {
|
||||||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
TriesInMemory uint64 // Number of recent tries to keep in memory
|
TriesInMemory uint64 // Number of recent tries to keep in memory
|
||||||
|
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
||||||
|
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
|
||||||
|
|
||||||
SnapshotNoBuild bool // Whether the background generation is allowed
|
SnapshotNoBuild bool // Whether the background generation is allowed
|
||||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// triedbConfig derives the configures for trie database.
|
||||||
|
func (c *CacheConfig) triedbConfig() *trie.Config {
|
||||||
|
config := &trie.Config{Preimages: c.Preimages}
|
||||||
|
if c.StateScheme == rawdb.HashScheme {
|
||||||
|
config.HashDB = &hashdb.Config{
|
||||||
|
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.StateScheme == rawdb.PathScheme {
|
||||||
|
config.PathDB = &pathdb.Config{
|
||||||
|
StateHistory: c.StateHistory,
|
||||||
|
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||||
|
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
// defaultCacheConfig are the default caching values if none are specified by the
|
// defaultCacheConfig are the default caching values if none are specified by the
|
||||||
// user (also used during testing).
|
// user (also used during testing).
|
||||||
var defaultCacheConfig = &CacheConfig{
|
var defaultCacheConfig = &CacheConfig{
|
||||||
|
|
@ -165,6 +189,15 @@ var defaultCacheConfig = &CacheConfig{
|
||||||
SnapshotLimit: 256,
|
SnapshotLimit: 256,
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
TriesInMemory: 1024,
|
TriesInMemory: 1024,
|
||||||
|
StateScheme: rawdb.HashScheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultCacheConfigWithScheme returns a deep copied default cache config with
|
||||||
|
// a provided trie node scheme.
|
||||||
|
func DefaultCacheConfigWithScheme(scheme string) *CacheConfig {
|
||||||
|
config := *defaultCacheConfig
|
||||||
|
config.StateScheme = scheme
|
||||||
|
return &config
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultCacheConfig = defaultCacheConfig
|
var DefaultCacheConfig = defaultCacheConfig
|
||||||
|
|
@ -265,10 +298,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
cacheConfig.TriesInMemory = defaultCacheConfig.TriesInMemory
|
cacheConfig.TriesInMemory = defaultCacheConfig.TriesInMemory
|
||||||
}
|
}
|
||||||
// Open trie database with provided config
|
// Open trie database with provided config
|
||||||
triedb := trie.NewDatabaseWithConfig(db, &trie.Config{
|
triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
|
||||||
Cache: cacheConfig.TrieCleanLimit,
|
|
||||||
Preimages: cacheConfig.Preimages,
|
|
||||||
})
|
|
||||||
// Setup the genesis block, commit the provided genesis specification
|
// Setup the genesis block, commit the provided genesis specification
|
||||||
// to database if the genesis block is not present yet, or load the
|
// to database if the genesis block is not present yet, or load the
|
||||||
// stored one from database.
|
// stored one from database.
|
||||||
|
|
@ -330,6 +361,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
bc.currentFinalBlock.Store(nil)
|
bc.currentFinalBlock.Store(nil)
|
||||||
bc.currentSafeBlock.Store(nil)
|
bc.currentSafeBlock.Store(nil)
|
||||||
|
|
||||||
|
// Update chain info data metrics
|
||||||
|
chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()})
|
||||||
|
|
||||||
// If Geth is initialized with an external ancient store, re-initialize the
|
// If Geth is initialized with an external ancient store, re-initialize the
|
||||||
// missing chain indexes and chain flags. This procedure can survive crash
|
// missing chain indexes and chain flags. This procedure can survive crash
|
||||||
// and can be resumed in next restart since chain flags are updated in last step.
|
// and can be resumed in next restart since chain flags are updated in last step.
|
||||||
|
|
@ -340,34 +374,42 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
if err := bc.loadLastState(); err != nil {
|
if err := bc.loadLastState(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Make sure the state associated with the block is available
|
// Make sure the state associated with the block is available, or log out
|
||||||
|
// if there is no available state, waiting for state sync.
|
||||||
head := bc.CurrentBlock()
|
head := bc.CurrentBlock()
|
||||||
// nolint:nestif
|
// nolint:nestif
|
||||||
if !bc.HasState(head.Root) {
|
if !bc.HasState(head.Root) {
|
||||||
// Head state is missing, before the state recovery, find out the
|
if head.Number.Uint64() == 0 {
|
||||||
// disk layer point of snapshot(if it's enabled). Make sure the
|
// The genesis state is missing, which is only possible in the path-based
|
||||||
// rewound point is lower than disk layer.
|
// scheme. This situation occurs when the initial state sync is not finished
|
||||||
var diskRoot common.Hash
|
// yet, or the chain head is rewound below the pivot point. In both scenarios,
|
||||||
if bc.cacheConfig.SnapshotLimit > 0 {
|
// there is no possible recovery approach except for rerunning a snap sync.
|
||||||
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
// Do nothing here until the state syncer picks it up.
|
||||||
}
|
log.Info("Genesis state is missing, wait state sync")
|
||||||
|
|
||||||
if diskRoot != (common.Hash{}) {
|
|
||||||
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot)
|
|
||||||
|
|
||||||
snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Chain rewound, persist old snapshot number to indicate recovery procedure
|
|
||||||
if snapDisk != 0 {
|
|
||||||
rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
|
// Head state is missing, before the state recovery, find out the
|
||||||
|
// disk layer point of snapshot(if it's enabled). Make sure the
|
||||||
|
// rewound point is lower than disk layer.
|
||||||
|
var diskRoot common.Hash
|
||||||
|
if bc.cacheConfig.SnapshotLimit > 0 {
|
||||||
|
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
||||||
|
}
|
||||||
|
if diskRoot != (common.Hash{}) {
|
||||||
|
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot)
|
||||||
|
|
||||||
if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
|
snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Chain rewound, persist old snapshot number to indicate recovery procedure
|
||||||
|
if snapDisk != 0 {
|
||||||
|
rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
|
||||||
|
if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -691,7 +733,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||||
|
|
||||||
if block == nil {
|
if block == nil {
|
||||||
// This should never happen. In practice, previsouly currentBlock
|
// This should never happen. In practice, previously currentBlock
|
||||||
// contained the entire block whereas now only a "marker", so there
|
// contained the entire block whereas now only a "marker", so there
|
||||||
// is an ever so slight chance for a race we should handle.
|
// is an ever so slight chance for a race we should handle.
|
||||||
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
||||||
|
|
@ -716,7 +758,7 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
|
||||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||||
|
|
||||||
if block == nil {
|
if block == nil {
|
||||||
// This should never happen. In practice, previsouly currentBlock
|
// This should never happen. In practice, previously currentBlock
|
||||||
// contained the entire block whereas now only a "marker", so there
|
// contained the entire block whereas now only a "marker", so there
|
||||||
// is an ever so slight chance for a race we should handle.
|
// is an ever so slight chance for a race we should handle.
|
||||||
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
||||||
|
|
@ -791,9 +833,8 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
|
|
||||||
newHeadBlock = bc.genesisBlock
|
newHeadBlock = bc.genesisBlock
|
||||||
} else {
|
} else {
|
||||||
// Block exists, keep rewinding until we find one with state,
|
// Block exists. Keep rewinding until either we find one with state
|
||||||
// keeping rewinding until we exceed the optional threshold
|
// or until we exceed the optional threshold root hash
|
||||||
// root hash
|
|
||||||
beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true)
|
beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
@ -801,8 +842,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root {
|
if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root {
|
||||||
beyondRoot, rootNumber = true, newHeadBlock.NumberU64()
|
beyondRoot, rootNumber = true, newHeadBlock.NumberU64()
|
||||||
}
|
}
|
||||||
|
if !bc.HasState(newHeadBlock.Root()) && !bc.stateRecoverable(newHeadBlock.Root()) {
|
||||||
if !bc.HasState(newHeadBlock.Root()) {
|
|
||||||
log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
|
log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
|
||||||
|
|
||||||
if pivot == nil || newHeadBlock.NumberU64() > *pivot {
|
if pivot == nil || newHeadBlock.NumberU64() > *pivot {
|
||||||
|
|
@ -821,23 +861,14 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
}
|
}
|
||||||
|
|
||||||
if beyondRoot || newHeadBlock.NumberU64() == 0 {
|
if beyondRoot || newHeadBlock.NumberU64() == 0 {
|
||||||
if newHeadBlock.NumberU64() == 0 {
|
if !bc.HasState(newHeadBlock.Root()) && bc.stateRecoverable(newHeadBlock.Root()) {
|
||||||
// Recommit the genesis state into disk in case the rewinding destination
|
// Rewind to a block with recoverable state. If the state is
|
||||||
// is genesis block and the relevant state is gone. In the future this
|
// missing, run the state recovery here.
|
||||||
// rewinding destination can be the earliest block stored in the chain
|
if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil {
|
||||||
// if the historical chain pruning is enabled. In that case the logic
|
log.Crit("Failed to rollback state", "err", err) // Shouldn't happen
|
||||||
// needs to be improved here.
|
|
||||||
if !bc.HasState(bc.genesisBlock.Root()) {
|
|
||||||
if err := CommitGenesisState(bc.db, bc.triedb, bc.genesisBlock.Hash()); err != nil {
|
|
||||||
log.Crit("Failed to commit genesis state", "err", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("Recommitted genesis state to disk")
|
|
||||||
}
|
}
|
||||||
|
log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -854,6 +885,15 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
// to low, so it's safe to update in-memory markers directly.
|
// to low, so it's safe to update in-memory markers directly.
|
||||||
bc.currentBlock.Store(newHeadBlock.Header())
|
bc.currentBlock.Store(newHeadBlock.Header())
|
||||||
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
|
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
|
||||||
|
|
||||||
|
// The head state is missing, which is only possible in the path-based
|
||||||
|
// scheme. This situation occurs when the chain head is rewound below
|
||||||
|
// the pivot point. In this scenario, there is no possible recovery
|
||||||
|
// approach except for rerunning a snap sync. Do nothing here until the
|
||||||
|
// state syncer picks it up.
|
||||||
|
if !bc.HasState(newHeadBlock.Root()) {
|
||||||
|
log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number(), "hash", newHeadBlock.Hash())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Rewind the snap block in a simpleton way to the target head
|
// Rewind the snap block in a simpleton way to the target head
|
||||||
if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() {
|
if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() {
|
||||||
|
|
@ -958,9 +998,13 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
|
||||||
if block == nil {
|
if block == nil {
|
||||||
return fmt.Errorf("non existent block [%x..]", hash[:4])
|
return fmt.Errorf("non existent block [%x..]", hash[:4])
|
||||||
}
|
}
|
||||||
|
// Reset the trie database with the fresh snap synced state.
|
||||||
root := block.Root()
|
root := block.Root()
|
||||||
|
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||||
|
if err := bc.triedb.Enable(root); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if !bc.HasState(root) {
|
if !bc.HasState(root) {
|
||||||
return fmt.Errorf("non existent state [%x..]", root[:4])
|
return fmt.Errorf("non existent state [%x..]", root[:4])
|
||||||
}
|
}
|
||||||
|
|
@ -1131,7 +1175,7 @@ func (bc *BlockChain) stopWithoutSaving() {
|
||||||
func (bc *BlockChain) Stop() {
|
func (bc *BlockChain) Stop() {
|
||||||
bc.stopWithoutSaving()
|
bc.stopWithoutSaving()
|
||||||
|
|
||||||
// Ensure that the entirety of the state snapshot is journalled to disk.
|
// Ensure that the entirety of the state snapshot is journaled to disk.
|
||||||
var snapBase common.Hash
|
var snapBase common.Hash
|
||||||
|
|
||||||
if bc.snaps != nil {
|
if bc.snaps != nil {
|
||||||
|
|
@ -1139,47 +1183,49 @@ func (bc *BlockChain) Stop() {
|
||||||
if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil {
|
if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil {
|
||||||
log.Error("Failed to journal state snapshot", "err", err)
|
log.Error("Failed to journal state snapshot", "err", err)
|
||||||
}
|
}
|
||||||
|
bc.snaps.Release()
|
||||||
}
|
}
|
||||||
|
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||||
|
// Ensure that the in-memory trie nodes are journaled to disk properly.
|
||||||
|
if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil {
|
||||||
|
log.Info("Failed to journal in-memory trie nodes", "err", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ensure the state of a recent block is also stored to disk before exiting.
|
||||||
|
// We're writing three different states to catch different restart scenarios:
|
||||||
|
// - HEAD: So we don't need to reprocess any blocks in the general case
|
||||||
|
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
|
||||||
|
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
|
||||||
|
if !bc.cacheConfig.TrieDirtyDisabled {
|
||||||
|
triedb := bc.triedb
|
||||||
|
|
||||||
// Ensure the state of a recent block is also stored to disk before exiting.
|
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
|
||||||
// We're writing three different states to catch different restart scenarios:
|
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
|
||||||
// - HEAD: So we don't need to reprocess any blocks in the general case
|
recent := bc.GetBlockByNumber(number - offset)
|
||||||
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
|
|
||||||
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
|
|
||||||
if !bc.cacheConfig.TrieDirtyDisabled {
|
|
||||||
triedb := bc.triedb
|
|
||||||
|
|
||||||
for _, offset := range []uint64{0, 1, bc.cacheConfig.TriesInMemory - 1} {
|
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
|
||||||
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
|
if err := triedb.Commit(recent.Root(), true); err != nil {
|
||||||
recent := bc.GetBlockByNumber(number - offset)
|
log.Error("Failed to commit recent state trie", "err", err)
|
||||||
|
}
|
||||||
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
|
}
|
||||||
|
}
|
||||||
if err := triedb.Commit(recent.Root(), true); err != nil {
|
if snapBase != (common.Hash{}) {
|
||||||
|
log.Info("Writing snapshot state to disk", "root", snapBase)
|
||||||
|
if err := triedb.Commit(snapBase, true); err != nil {
|
||||||
log.Error("Failed to commit recent state trie", "err", err)
|
log.Error("Failed to commit recent state trie", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
for !bc.triegc.Empty() {
|
||||||
|
triedb.Dereference(bc.triegc.PopItem())
|
||||||
if snapBase != (common.Hash{}) {
|
}
|
||||||
log.Info("Writing snapshot state to disk", "root", snapBase)
|
if _, nodes, _ := triedb.Size(); nodes != 0 { // all memory is contained within the nodes return for hashdb
|
||||||
|
log.Error("Dangling trie nodes after full cleanup")
|
||||||
if err := triedb.Commit(snapBase, true); err != nil {
|
|
||||||
log.Error("Failed to commit recent state trie", "err", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for !bc.triegc.Empty() {
|
|
||||||
triedb.Dereference(bc.triegc.PopItem())
|
|
||||||
}
|
|
||||||
|
|
||||||
if size, _ := triedb.Size(); size != 0 {
|
|
||||||
log.Error("Dangling trie nodes after full cleanup")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Flush the collected preimages to disk
|
// Close the trie database, release all the held resources as the last step.
|
||||||
if err := bc.stateCache.TrieDB().Close(); err != nil {
|
if err := bc.triedb.Close(); err != nil {
|
||||||
log.Error("Failed to close trie db", "err", err)
|
log.Error("Failed to close trie database", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Blockchain stopped")
|
log.Info("Blockchain stopped")
|
||||||
|
|
@ -1239,21 +1285,30 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
ancientReceipts, liveReceipts []types.Receipts
|
ancientReceipts, liveReceipts []types.Receipts
|
||||||
)
|
)
|
||||||
// Do a sanity check that the provided chain is actually ordered and linked
|
// Do a sanity check that the provided chain is actually ordered and linked
|
||||||
for i := 0; i < len(blockChain); i++ {
|
for i, block := range blockChain {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
|
prev := blockChain[i-1]
|
||||||
log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(),
|
if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() {
|
||||||
"prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash())
|
log.Error("Non contiguous receipt insert",
|
||||||
|
"number", block.Number(), "hash", block.Hash(), "parent", block.ParentHash(),
|
||||||
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, blockChain[i-1].NumberU64(),
|
"prevnumber", prev.Number(), "prevhash", prev.Hash())
|
||||||
blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
|
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])",
|
||||||
|
i-1, prev.NumberU64(), prev.Hash().Bytes()[:4],
|
||||||
|
i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if block.NumberU64() <= ancientLimit {
|
||||||
if blockChain[i].NumberU64() <= ancientLimit {
|
ancientBlocks, ancientReceipts = append(ancientBlocks, block), append(ancientReceipts, receiptChain[i])
|
||||||
ancientBlocks, ancientReceipts = append(ancientBlocks, blockChain[i]), append(ancientReceipts, receiptChain[i])
|
|
||||||
} else {
|
} else {
|
||||||
liveBlocks, liveReceipts = append(liveBlocks, blockChain[i]), append(liveReceipts, receiptChain[i])
|
liveBlocks, liveReceipts = append(liveBlocks, block), append(liveReceipts, receiptChain[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we also validate that blob transactions in the block do not contain a sidecar.
|
||||||
|
// While the sidecar does not affect the block hash / tx hash, sending blobs within a block is not allowed.
|
||||||
|
for txIndex, tx := range block.Transactions() {
|
||||||
|
if tx.Type() == types.BlobTxType && tx.BlobTxSidecar() != nil {
|
||||||
|
return 0, fmt.Errorf("block #%d contains unexpected blob sidecar in tx at index %d", block.NumberU64(), txIndex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1361,8 +1416,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
// a background routine to re-indexed all indices in [ancients - txlookupLimit, ancients)
|
// a background routine to re-indexed all indices in [ancients - txlookupLimit, ancients)
|
||||||
// range. In this case, all tx indices of newly imported blocks should be
|
// range. In this case, all tx indices of newly imported blocks should be
|
||||||
// generated.
|
// generated.
|
||||||
var batch = bc.db.NewBatch()
|
batch := bc.db.NewBatch()
|
||||||
|
|
||||||
for i, block := range blockChain {
|
for i, block := range blockChain {
|
||||||
if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit {
|
if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit {
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
||||||
|
|
@ -1647,6 +1701,11 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*types.Log{}, err
|
return []*types.Log{}, err
|
||||||
}
|
}
|
||||||
|
// If node is running in path mode, skip explicit gc operation
|
||||||
|
// which is unnecessary in this mode.
|
||||||
|
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// If we're running an archive node, always flush
|
// If we're running an archive node, always flush
|
||||||
if bc.cacheConfig.TrieDirtyDisabled {
|
if bc.cacheConfig.TrieDirtyDisabled {
|
||||||
return []*types.Log{}, bc.triedb.Commit(root, false)
|
return []*types.Log{}, bc.triedb.Commit(root, false)
|
||||||
|
|
@ -1655,15 +1714,15 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
bc.triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
|
bc.triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
|
||||||
bc.triegc.Push(root, -int64(block.NumberU64()))
|
bc.triegc.Push(root, -int64(block.NumberU64()))
|
||||||
|
|
||||||
current := block.NumberU64()
|
|
||||||
// Flush limits are not considered for the first TriesInMemory blocks.
|
// Flush limits are not considered for the first TriesInMemory blocks.
|
||||||
if current <= bc.cacheConfig.TriesInMemory {
|
current := block.NumberU64()
|
||||||
return []*types.Log{}, nil
|
if current <= TriesInMemory {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||||
var (
|
var (
|
||||||
nodes, imgs = bc.triedb.Size()
|
_, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb
|
||||||
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
|
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
if nodes > limit || imgs > 4*1024*1024 {
|
if nodes > limit || imgs > 4*1024*1024 {
|
||||||
|
|
@ -2246,8 +2305,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
stats.processed++
|
stats.processed++
|
||||||
stats.usedGas += usedGas
|
stats.usedGas += usedGas
|
||||||
|
|
||||||
dirty, _ := bc.triedb.Size()
|
var snapDiffItems, snapBufItems common.StorageSize
|
||||||
stats.report(chain, it.index, dirty, setHead)
|
if bc.snaps != nil {
|
||||||
|
snapDiffItems, snapBufItems = bc.snaps.Size()
|
||||||
|
}
|
||||||
|
trieDiffNodes, trieBufNodes, _ := bc.triedb.Size()
|
||||||
|
stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead)
|
||||||
|
|
||||||
if !setHead {
|
if !setHead {
|
||||||
// After merge we expect few side chains. Simply count
|
// After merge we expect few side chains. Simply count
|
||||||
|
|
@ -2420,6 +2483,12 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
|
|
||||||
parent := it.previous()
|
parent := it.previous()
|
||||||
for parent != nil && !bc.HasState(parent.Root) {
|
for parent != nil && !bc.HasState(parent.Root) {
|
||||||
|
if bc.stateRecoverable(parent.Root) {
|
||||||
|
if err := bc.triedb.Recover(parent.Root); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
hashes = append(hashes, parent.Hash())
|
hashes = append(hashes, parent.Hash())
|
||||||
numbers = append(numbers, parent.Number.Uint64())
|
numbers = append(numbers, parent.Number.Uint64())
|
||||||
|
|
||||||
|
|
@ -2482,6 +2551,12 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
|
||||||
)
|
)
|
||||||
|
|
||||||
for parent != nil && !bc.HasState(parent.Root()) {
|
for parent != nil && !bc.HasState(parent.Root()) {
|
||||||
|
if bc.stateRecoverable(parent.Root()) {
|
||||||
|
if err := bc.triedb.Recover(parent.Root()); err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
hashes = append(hashes, parent.Hash())
|
hashes = append(hashes, parent.Hash())
|
||||||
numbers = append(numbers, parent.NumberU64())
|
numbers = append(numbers, parent.NumberU64())
|
||||||
parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1)
|
parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1)
|
||||||
|
|
@ -2944,6 +3019,12 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
|
||||||
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
|
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
|
||||||
defer func() { close(done) }()
|
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
|
// The tail flag is not existent, it means the node is just initialized
|
||||||
// and all blocks(may from ancient store) are not indexed yet.
|
// and all blocks(may from ancient store) are not indexed yet.
|
||||||
if tail == nil {
|
if tail == nil {
|
||||||
|
|
@ -3007,6 +3088,15 @@ func (bc *BlockChain) maintainTxIndex() {
|
||||||
}
|
}
|
||||||
|
|
||||||
defer sub.Unsubscribe()
|
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 {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|
@ -3103,7 +3193,7 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
|
||||||
bc.flushInterval.Store(int64(interval))
|
bc.flushInterval.Store(int64(interval))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTrieFlushInterval gets the in-memroy tries flush interval
|
// GetTrieFlushInterval gets the in-memory tries flush interval
|
||||||
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
|
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
|
||||||
return time.Duration(bc.flushInterval.Load())
|
return time.Duration(bc.flushInterval.Load())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ const statsReportLimit = 8 * time.Second
|
||||||
|
|
||||||
// report prints statistics if some number of blocks have been processed
|
// report prints statistics if some number of blocks have been processed
|
||||||
// or more than a few seconds have passed since the last message.
|
// or more than a few seconds have passed since the last message.
|
||||||
func (st *insertStats) report(chain []*types.Block, index int, dirty common.StorageSize, setHead bool) {
|
func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, snapBufItems, trieDiffNodes, triebufNodes common.StorageSize, setHead bool) {
|
||||||
// Fetch the timings for the batch
|
// Fetch the timings for the batch
|
||||||
var (
|
var (
|
||||||
now = mclock.Now()
|
now = mclock.Now()
|
||||||
|
|
@ -64,8 +64,16 @@ func (st *insertStats) report(chain []*types.Block, index int, dirty common.Stor
|
||||||
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
||||||
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
||||||
}
|
}
|
||||||
|
if snapDiffItems != 0 || snapBufItems != 0 { // snapshots enabled
|
||||||
context = append(context, []interface{}{"dirty", dirty}...)
|
context = append(context, []interface{}{"snapdiffs", snapDiffItems}...)
|
||||||
|
if snapBufItems != 0 { // future snapshot refactor
|
||||||
|
context = append(context, []interface{}{"snapdirty", snapBufItems}...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if trieDiffNodes != 0 { // pathdb
|
||||||
|
context = append(context, []interface{}{"triediffs", trieDiffNodes}...)
|
||||||
|
}
|
||||||
|
context = append(context, []interface{}{"triedirty", triebufNodes}...)
|
||||||
|
|
||||||
if st.queued > 0 {
|
if st.queued > 0 {
|
||||||
context = append(context, []interface{}{"queued", st.queued}...)
|
context = append(context, []interface{}{"queued", st.queued}...)
|
||||||
|
|
|
||||||
|
|
@ -330,10 +330,16 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
|
||||||
return bc.HasState(block.Root())
|
return bc.HasState(block.Root())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrieNode retrieves a blob of data associated with a trie node
|
// stateRecoverable checks if the specified state is recoverable.
|
||||||
// either from ephemeral in-memory cache, or from persistent storage.
|
// Note, this function assumes the state is not present, because
|
||||||
func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
|
// state is not treated as recoverable if it's available, thus
|
||||||
return bc.stateCache.TrieDB().Node(hash)
|
// false will be returned in this case.
|
||||||
|
func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
|
||||||
|
if bc.triedb.Scheme() == rawdb.HashScheme {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
result, _ := bc.triedb.Recoverable(root)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue