mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
Merge tag 'v1.14.13' into manav/upstream_merge_v1.14.13
This commit is contained in:
commit
1acf5e6eb0
386 changed files with 26064 additions and 7627 deletions
24
.gitignore
vendored
24
.gitignore
vendored
|
|
@ -4,16 +4,11 @@
|
||||||
# or operating system, you probably want to add a global ignore instead:
|
# or operating system, you probably want to add a global ignore instead:
|
||||||
# git config --global core.excludesfile ~/.gitignore_global
|
# git config --global core.excludesfile ~/.gitignore_global
|
||||||
|
|
||||||
/tmp
|
|
||||||
*/**/*un~
|
*/**/*un~
|
||||||
*/**/*.test
|
*/**/*.test
|
||||||
*un~
|
*un~
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*/**/.DS_Store
|
*/**/.DS_Store
|
||||||
.ethtest
|
|
||||||
*/**/*tx_database*
|
|
||||||
*/**/*dapps*
|
|
||||||
build/_vendor/pkg
|
|
||||||
|
|
||||||
cover.out
|
cover.out
|
||||||
|
|
||||||
|
|
@ -48,23 +43,4 @@ profile.cov
|
||||||
# VS Code
|
# VS Code
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
# dashboard
|
|
||||||
/dashboard/assets/flow-typed
|
|
||||||
/dashboard/assets/node_modules
|
|
||||||
/dashboard/assets/stats.json
|
|
||||||
/dashboard/assets/bundle.js
|
|
||||||
/dashboard/assets/bundle.js.map
|
|
||||||
/dashboard/assets/package-lock.json
|
|
||||||
|
|
||||||
**/yarn-error.log
|
|
||||||
./test
|
|
||||||
./bor-debug-*
|
|
||||||
|
|
||||||
dist
|
|
||||||
|
|
||||||
.dccache
|
|
||||||
|
|
||||||
*.csv
|
|
||||||
logs/
|
|
||||||
|
|
||||||
tests/spec-tests/
|
tests/spec-tests/
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,14 @@ linters:
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- bidichk
|
- bidichk
|
||||||
- durationcheck
|
- durationcheck
|
||||||
- exportloopref
|
- copyloopvar
|
||||||
- whitespace
|
- whitespace
|
||||||
- revive # only certain checks enabled
|
- revive # only certain checks enabled
|
||||||
|
- durationcheck
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- reassign
|
||||||
|
- mirror
|
||||||
|
- tenv
|
||||||
### linters we tried and will not be using:
|
### linters we tried and will not be using:
|
||||||
###
|
###
|
||||||
# - structcheck # lots of false positives
|
# - structcheck # lots of false positives
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
before_install:
|
before_install:
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go dockerx -platform "linux/amd64,linux/arm64" -upload ethereum/client-go
|
- go run build/ci.go dockerx -platform "linux/amd64,linux/arm64,linux/riscv64" -upload ethereum/client-go
|
||||||
|
|
||||||
# This builder does the Ubuntu PPA upload
|
# This builder does the Ubuntu PPA upload
|
||||||
- stage: build
|
- stage: build
|
||||||
|
|
|
||||||
|
|
@ -1304,7 +1304,6 @@ func TestUnpackRevert(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for index, c := range cases {
|
for index, c := range cases {
|
||||||
index, c := index, c
|
|
||||||
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
|
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got, err := UnpackRevert(common.Hex2Bytes(c.input))
|
got, err := UnpackRevert(common.Hex2Bytes(c.input))
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
}
|
}
|
||||||
// Parse library references.
|
// Parse library references.
|
||||||
for pattern, name := range libs {
|
for pattern, name := range libs {
|
||||||
matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin))
|
matched, err := regexp.MatchString("__\\$"+pattern+"\\$__", contracts[types[i]].InputBin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
|
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,6 @@ func TestEventTupleUnpack(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
|
err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
|
||||||
if tc.error == "" {
|
if tc.error == "" {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import (
|
||||||
func TestPack(t *testing.T) {
|
func TestPack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for i, test := range packUnpackTests {
|
for i, test := range packUnpackTests {
|
||||||
i, test := i, test
|
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
encb, err := hex.DecodeString(test.packed)
|
encb, err := hex.DecodeString(test.packed)
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,6 @@ var reflectTests = []reflectTest{
|
||||||
func TestReflectNameToStruct(t *testing.T) {
|
func TestReflectNameToStruct(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for _, test := range reflectTests {
|
for _, test := range reflectTests {
|
||||||
test := test
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
|
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,6 @@ func TestMakeTopics(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got, err := MakeTopics(tt.args.query...)
|
got, err := MakeTopics(tt.args.query...)
|
||||||
|
|
@ -375,7 +374,6 @@ func TestParseTopics(t *testing.T) {
|
||||||
tests := setupTopicsTests()
|
tests := setupTopicsTests()
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
createObj := tt.args.createObj()
|
createObj := tt.args.createObj()
|
||||||
|
|
@ -396,7 +394,6 @@ func TestParseTopicsIntoMap(t *testing.T) {
|
||||||
tests := setupTopicsTests()
|
tests := setupTopicsTests()
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
outMap := make(map[string]interface{})
|
outMap := make(map[string]interface{})
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,6 @@ func TestMethodMultiReturn(t *testing.T) {
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
err := abi.UnpackIntoInterface(tc.dest, "multi", data)
|
err := abi.UnpackIntoInterface(tc.dest, "multi", data)
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ func byURL(a, b accounts.Account) int {
|
||||||
return a.URL.Cmp(b.URL)
|
return a.URL.Cmp(b.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AmbiguousAddrError is returned when attempting to unlock
|
// AmbiguousAddrError is returned when an address matches multiple files.
|
||||||
// an address for which more than one file exists.
|
|
||||||
type AmbiguousAddrError struct {
|
type AmbiguousAddrError struct {
|
||||||
Addr common.Address
|
Addr common.Address
|
||||||
Matches []accounts.Account
|
Matches []accounts.Account
|
||||||
|
|
|
||||||
1
accounts/keystore/testdata/dupes/1
vendored
1
accounts/keystore/testdata/dupes/1
vendored
|
|
@ -1 +0,0 @@
|
||||||
{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3}
|
|
||||||
1
accounts/keystore/testdata/dupes/2
vendored
1
accounts/keystore/testdata/dupes/2
vendored
|
|
@ -1 +0,0 @@
|
||||||
{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3}
|
|
||||||
1
accounts/keystore/testdata/dupes/foo
vendored
1
accounts/keystore/testdata/dupes/foo
vendored
|
|
@ -1 +0,0 @@
|
||||||
{"address":"7ef5a6135f1fd6a02593eedc869c6d41d934aef8","crypto":{"cipher":"aes-128-ctr","ciphertext":"1d0839166e7a15b9c1333fc865d69858b22df26815ccf601b28219b6192974e1","cipherparams":{"iv":"8df6caa7ff1b00c4e871f002cb7921ed"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"e5e6ef3f4ea695f496b643ebd3f75c0aa58ef4070e90c80c5d3fb0241bf1595c"},"mac":"6d16dfde774845e4585357f24bce530528bc69f4f84e1e22880d34fa45c273e5"},"id":"950077c7-71e3-4c44-a4a1-143919141ed4","version":3}
|
|
||||||
|
|
@ -29,12 +29,9 @@ import (
|
||||||
// the manager will buffer in its channel.
|
// the manager will buffer in its channel.
|
||||||
const managerSubBufferSize = 50
|
const managerSubBufferSize = 50
|
||||||
|
|
||||||
// Config contains the settings of the global account manager.
|
// Config is a legacy struct which is not used
|
||||||
//
|
|
||||||
// TODO(rjl493456442, karalabe, holiman): Get rid of this when account management
|
|
||||||
// is removed in favor of Clef.
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
InsecureUnlockAllowed bool // Whether account unlocking in insecure environment is allowed
|
InsecureUnlockAllowed bool // Unused legacy-parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBackendEvent lets the manager know it should
|
// newBackendEvent lets the manager know it should
|
||||||
|
|
@ -47,7 +44,6 @@ type newBackendEvent struct {
|
||||||
// Manager is an overarching account manager that can communicate with various
|
// Manager is an overarching account manager that can communicate with various
|
||||||
// backends for signing transactions.
|
// backends for signing transactions.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
config *Config // Global account manager configurations
|
|
||||||
backends map[reflect.Type][]Backend // Index of backends currently registered
|
backends map[reflect.Type][]Backend // Index of backends currently registered
|
||||||
updaters []event.Subscription // Wallet update subscriptions for all backends
|
updaters []event.Subscription // Wallet update subscriptions for all backends
|
||||||
updates chan WalletEvent // Subscription sink for backend wallet changes
|
updates chan WalletEvent // Subscription sink for backend wallet changes
|
||||||
|
|
@ -78,7 +74,6 @@ func NewManager(config *Config, backends ...Backend) *Manager {
|
||||||
}
|
}
|
||||||
// Assemble the account manager and return
|
// Assemble the account manager and return
|
||||||
am := &Manager{
|
am := &Manager{
|
||||||
config: config,
|
|
||||||
backends: make(map[reflect.Type][]Backend),
|
backends: make(map[reflect.Type][]Backend),
|
||||||
updaters: subs,
|
updaters: subs,
|
||||||
updates: updates,
|
updates: updates,
|
||||||
|
|
@ -109,11 +104,6 @@ func (am *Manager) Close() error {
|
||||||
return <-errc
|
return <-errc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config returns the configuration of account manager.
|
|
||||||
func (am *Manager) Config() *Config {
|
|
||||||
return am.config
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddBackend starts the tracking of an additional backend for wallet updates.
|
// AddBackend starts the tracking of an additional backend for wallet updates.
|
||||||
// cmd/geth assumes once this func returns the backends have been already integrated.
|
// cmd/geth assumes once this func returns the backends have been already integrated.
|
||||||
func (am *Manager) AddBackend(backend Backend) {
|
func (am *Manager) AddBackend(backend Backend) {
|
||||||
|
|
|
||||||
|
|
@ -353,8 +353,22 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
||||||
return common.Address{}, nil, err
|
return common.Address{}, nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
|
if tx.Type() == types.DynamicFeeTxType {
|
||||||
return common.Address{}, nil, err
|
if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
|
// append type to transaction
|
||||||
|
txrlp = append([]byte{tx.Type()}, txrlp...)
|
||||||
|
} else if tx.Type() == types.AccessListTxType {
|
||||||
|
if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
|
// append type to transaction
|
||||||
|
txrlp = append([]byte{tx.Type()}, txrlp...)
|
||||||
|
} else if tx.Type() == types.LegacyTxType {
|
||||||
|
if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,7 +383,9 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
||||||
// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
|
// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
|
||||||
// https://github.com/LedgerHQ/app-ethereum/issues/409
|
// https://github.com/LedgerHQ/app-ethereum/issues/409
|
||||||
chunk := 255
|
chunk := 255
|
||||||
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
|
if tx.Type() == types.LegacyTxType {
|
||||||
|
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(payload) > 0 {
|
for len(payload) > 0 {
|
||||||
|
|
@ -398,8 +414,11 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
||||||
if chainID == nil {
|
if chainID == nil {
|
||||||
signer = new(types.HomesteadSigner)
|
signer = new(types.HomesteadSigner)
|
||||||
} else {
|
} else {
|
||||||
signer = types.NewEIP155Signer(chainID)
|
signer = types.LatestSignerForChainID(chainID)
|
||||||
signature[64] -= byte(chainID.Uint64()*2 + 35)
|
// For non-legacy transactions, V is 0 or 1, no need to subtract here.
|
||||||
|
if tx.Type() == types.LegacyTxType {
|
||||||
|
signature[64] -= byte(chainID.Uint64()*2 + 35)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signed, err := tx.WithSignature(signer, signature)
|
signed, err := tx.WithSignature(signer, signature)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ for:
|
||||||
- image: Ubuntu
|
- image: Ubuntu
|
||||||
build_script:
|
build_script:
|
||||||
- go run build/ci.go lint
|
- go run build/ci.go lint
|
||||||
- go run build/ci.go generate -verify
|
- go run build/ci.go check_tidy
|
||||||
|
- go run build/ci.go check_generate
|
||||||
|
- go run build/ci.go check_baddeps
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
test_script:
|
test_script:
|
||||||
- go run build/ci.go test -dlgo -short
|
- go run build/ci.go test -dlgo -short
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,22 @@
|
||||||
package blsync
|
package blsync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/light"
|
"github.com/ethereum/go-ethereum/beacon/light"
|
||||||
"github.com/ethereum/go-ethereum/beacon/light/api"
|
"github.com/ethereum/go-ethereum/beacon/light/api"
|
||||||
"github.com/ethereum/go-ethereum/beacon/light/request"
|
"github.com/ethereum/go-ethereum/beacon/light/request"
|
||||||
"github.com/ethereum/go-ethereum/beacon/light/sync"
|
"github.com/ethereum/go-ethereum/beacon/light/sync"
|
||||||
|
"github.com/ethereum/go-ethereum/beacon/params"
|
||||||
"github.com/ethereum/go-ethereum/beacon/types"
|
"github.com/ethereum/go-ethereum/beacon/types"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
urls []string
|
urls []string
|
||||||
customHeader map[string]string
|
customHeader map[string]string
|
||||||
chainConfig *lightClientConfig
|
config *params.ClientConfig
|
||||||
scheduler *request.Scheduler
|
scheduler *request.Scheduler
|
||||||
blockSync *beaconBlockSync
|
blockSync *beaconBlockSync
|
||||||
engineRPC *rpc.Client
|
engineRPC *rpc.Client
|
||||||
|
|
@ -44,34 +41,18 @@ type Client struct {
|
||||||
engineClient *engineClient
|
engineClient *engineClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx *cli.Context) *Client {
|
func NewClient(config params.ClientConfig) *Client {
|
||||||
if !ctx.IsSet(utils.BeaconApiFlag.Name) {
|
|
||||||
utils.Fatalf("Beacon node light client API URL not specified")
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
chainConfig = makeChainConfig(ctx)
|
|
||||||
customHeader = make(map[string]string)
|
|
||||||
)
|
|
||||||
for _, s := range ctx.StringSlice(utils.BeaconApiHeaderFlag.Name) {
|
|
||||||
kv := strings.Split(s, ":")
|
|
||||||
if len(kv) != 2 {
|
|
||||||
utils.Fatalf("Invalid custom API header entry: %s", s)
|
|
||||||
}
|
|
||||||
customHeader[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// create data structures
|
// create data structures
|
||||||
var (
|
var (
|
||||||
db = memorydb.New()
|
db = memorydb.New()
|
||||||
threshold = ctx.Int(utils.BeaconThresholdFlag.Name)
|
committeeChain = light.NewCommitteeChain(db, &config.ChainConfig, config.Threshold, !config.NoFilter)
|
||||||
committeeChain = light.NewCommitteeChain(db, chainConfig.ChainConfig, threshold, !ctx.Bool(utils.BeaconNoFilterFlag.Name))
|
headTracker = light.NewHeadTracker(committeeChain, config.Threshold)
|
||||||
headTracker = light.NewHeadTracker(committeeChain, threshold)
|
|
||||||
)
|
)
|
||||||
headSync := sync.NewHeadSync(headTracker, committeeChain)
|
headSync := sync.NewHeadSync(headTracker, committeeChain)
|
||||||
|
|
||||||
// set up scheduler and sync modules
|
// set up scheduler and sync modules
|
||||||
scheduler := request.NewScheduler()
|
scheduler := request.NewScheduler()
|
||||||
checkpointInit := sync.NewCheckpointInit(committeeChain, chainConfig.Checkpoint)
|
checkpointInit := sync.NewCheckpointInit(committeeChain, config.Checkpoint)
|
||||||
forwardSync := sync.NewForwardUpdateSync(committeeChain)
|
forwardSync := sync.NewForwardUpdateSync(committeeChain)
|
||||||
beaconBlockSync := newBeaconBlockSync(headTracker)
|
beaconBlockSync := newBeaconBlockSync(headTracker)
|
||||||
scheduler.RegisterTarget(headTracker)
|
scheduler.RegisterTarget(headTracker)
|
||||||
|
|
@ -83,9 +64,9 @@ func NewClient(ctx *cli.Context) *Client {
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
scheduler: scheduler,
|
scheduler: scheduler,
|
||||||
urls: ctx.StringSlice(utils.BeaconApiFlag.Name),
|
urls: config.Apis,
|
||||||
customHeader: customHeader,
|
customHeader: config.CustomHeader,
|
||||||
chainConfig: &chainConfig,
|
config: &config,
|
||||||
blockSync: beaconBlockSync,
|
blockSync: beaconBlockSync,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +78,7 @@ func (c *Client) SetEngineRPC(engine *rpc.Client) {
|
||||||
func (c *Client) Start() error {
|
func (c *Client) Start() error {
|
||||||
headCh := make(chan types.ChainHeadEvent, 16)
|
headCh := make(chan types.ChainHeadEvent, 16)
|
||||||
c.chainHeadSub = c.blockSync.SubscribeChainHead(headCh)
|
c.chainHeadSub = c.blockSync.SubscribeChainHead(headCh)
|
||||||
c.engineClient = startEngineClient(c.chainConfig, c.engineRPC, headCh)
|
c.engineClient = startEngineClient(c.config, c.engineRPC, headCh)
|
||||||
|
|
||||||
c.scheduler.Start()
|
c.scheduler.Start()
|
||||||
for _, url := range c.urls {
|
for _, url := range c.urls {
|
||||||
|
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
// Copyright 2022 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package blsync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/types"
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// lightClientConfig contains beacon light client configuration
|
|
||||||
type lightClientConfig struct {
|
|
||||||
*types.ChainConfig
|
|
||||||
Checkpoint common.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
MainnetConfig = lightClientConfig{
|
|
||||||
ChainConfig: (&types.ChainConfig{
|
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
|
||||||
GenesisTime: 1606824023,
|
|
||||||
}).
|
|
||||||
AddFork("GENESIS", 0, []byte{0, 0, 0, 0}).
|
|
||||||
AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}).
|
|
||||||
AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}).
|
|
||||||
AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}).
|
|
||||||
AddFork("DENEB", 269568, []byte{4, 0, 0, 0}),
|
|
||||||
Checkpoint: common.HexToHash("0x388be41594ec7d6a6894f18c73f3469f07e2c19a803de4755d335817ed8e2e5a"),
|
|
||||||
}
|
|
||||||
|
|
||||||
SepoliaConfig = lightClientConfig{
|
|
||||||
ChainConfig: (&types.ChainConfig{
|
|
||||||
GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"),
|
|
||||||
GenesisTime: 1655733600,
|
|
||||||
}).
|
|
||||||
AddFork("GENESIS", 0, []byte{144, 0, 0, 105}).
|
|
||||||
AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}).
|
|
||||||
AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}).
|
|
||||||
AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}).
|
|
||||||
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}),
|
|
||||||
Checkpoint: common.HexToHash("0x1005a6d9175e96bfbce4d35b80f468e9bff0b674e1e861d16e09e10005a58e81"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
|
||||||
var config lightClientConfig
|
|
||||||
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
|
||||||
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.BeaconConfigFlag)
|
|
||||||
switch {
|
|
||||||
case ctx.Bool(utils.MainnetFlag.Name):
|
|
||||||
config = MainnetConfig
|
|
||||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
|
||||||
config = SepoliaConfig
|
|
||||||
default:
|
|
||||||
if !customConfig {
|
|
||||||
config = MainnetConfig
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Genesis root and time should always be specified together with custom chain config
|
|
||||||
if customConfig {
|
|
||||||
if !ctx.IsSet(utils.BeaconGenesisRootFlag.Name) {
|
|
||||||
utils.Fatalf("Custom beacon chain config is specified but genesis root is missing")
|
|
||||||
}
|
|
||||||
if !ctx.IsSet(utils.BeaconGenesisTimeFlag.Name) {
|
|
||||||
utils.Fatalf("Custom beacon chain config is specified but genesis time is missing")
|
|
||||||
}
|
|
||||||
if !ctx.IsSet(utils.BeaconCheckpointFlag.Name) {
|
|
||||||
utils.Fatalf("Custom beacon chain config is specified but checkpoint is missing")
|
|
||||||
}
|
|
||||||
config.ChainConfig = &types.ChainConfig{
|
|
||||||
GenesisTime: ctx.Uint64(utils.BeaconGenesisTimeFlag.Name),
|
|
||||||
}
|
|
||||||
if c, err := hexutil.Decode(ctx.String(utils.BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 {
|
|
||||||
copy(config.GenesisValidatorsRoot[:len(c)], c)
|
|
||||||
} else {
|
|
||||||
utils.Fatalf("Invalid hex string", "beacon.genesis.gvroot", ctx.String(utils.BeaconGenesisRootFlag.Name), "error", err)
|
|
||||||
}
|
|
||||||
if err := config.ChainConfig.LoadForks(ctx.String(utils.BeaconConfigFlag.Name)); err != nil {
|
|
||||||
utils.Fatalf("Could not load beacon chain config file", "file name", ctx.String(utils.BeaconConfigFlag.Name), "error", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ctx.IsSet(utils.BeaconGenesisRootFlag.Name) {
|
|
||||||
utils.Fatalf("Genesis root is specified but custom beacon chain config is missing")
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.BeaconGenesisTimeFlag.Name) {
|
|
||||||
utils.Fatalf("Genesis time is specified but custom beacon chain config is missing")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Checkpoint is required with custom chain config and is optional with pre-defined config
|
|
||||||
if ctx.IsSet(utils.BeaconCheckpointFlag.Name) {
|
|
||||||
if c, err := hexutil.Decode(ctx.String(utils.BeaconCheckpointFlag.Name)); err == nil && len(c) <= 32 {
|
|
||||||
copy(config.Checkpoint[:len(c)], c)
|
|
||||||
} else {
|
|
||||||
utils.Fatalf("Invalid hex string", "beacon.checkpoint", ctx.String(utils.BeaconCheckpointFlag.Name), "error", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||||
|
"github.com/ethereum/go-ethereum/beacon/params"
|
||||||
"github.com/ethereum/go-ethereum/beacon/types"
|
"github.com/ethereum/go-ethereum/beacon/types"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
ctypes "github.com/ethereum/go-ethereum/core/types"
|
ctypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -31,14 +32,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type engineClient struct {
|
type engineClient struct {
|
||||||
config *lightClientConfig
|
config *params.ClientConfig
|
||||||
rpc *rpc.Client
|
rpc *rpc.Client
|
||||||
rootCtx context.Context
|
rootCtx context.Context
|
||||||
cancelRoot context.CancelFunc
|
cancelRoot context.CancelFunc
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func startEngineClient(config *lightClientConfig, rpc *rpc.Client, headCh <-chan types.ChainHeadEvent) *engineClient {
|
func startEngineClient(config *params.ClientConfig, rpc *rpc.Client, headCh <-chan types.ChainHeadEvent) *engineClient {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
ec := &engineClient{
|
ec := &engineClient{
|
||||||
config: config,
|
config: config,
|
||||||
|
|
@ -92,7 +93,7 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) (string, error) {
|
func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) (string, error) {
|
||||||
execData := engine.BlockToExecutableData(event.Block, nil, nil).ExecutionPayload
|
execData := engine.BlockToExecutableData(event.Block, nil, nil, nil).ExecutionPayload
|
||||||
|
|
||||||
var (
|
var (
|
||||||
method string
|
method string
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
Deposits types.Deposits `json:"depositRequests"`
|
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +62,6 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
enc.Withdrawals = e.Withdrawals
|
enc.Withdrawals = e.Withdrawals
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||||
enc.Deposits = e.Deposits
|
|
||||||
enc.ExecutionWitness = e.ExecutionWitness
|
enc.ExecutionWitness = e.ExecutionWitness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +86,6 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
Deposits *types.Deposits `json:"depositRequests"`
|
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,9 +190,6 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ExcessBlobGas != nil {
|
if dec.ExcessBlobGas != nil {
|
||||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
if dec.Deposits != nil {
|
|
||||||
e.Deposits = *dec.Deposits
|
|
||||||
}
|
|
||||||
if dec.ExecutionWitness != nil {
|
if dec.ExecutionWitness != nil {
|
||||||
e.ExecutionWitness = dec.ExecutionWitness
|
e.ExecutionWitness = dec.ExecutionWitness
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,21 @@ 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"`
|
||||||
|
Requests []hexutil.Bytes `json:"executionRequests"`
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness"`
|
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
if e.Requests != nil {
|
||||||
|
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
|
||||||
|
for k, v := range e.Requests {
|
||||||
|
enc.Requests[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
enc.Override = e.Override
|
enc.Override = e.Override
|
||||||
enc.Witness = e.Witness
|
enc.Witness = e.Witness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
|
|
@ -37,8 +44,9 @@ 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"`
|
||||||
|
Requests []hexutil.Bytes `json:"executionRequests"`
|
||||||
Override *bool `json:"shouldOverrideBuilder"`
|
Override *bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness"`
|
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec ExecutionPayloadEnvelope
|
var dec ExecutionPayloadEnvelope
|
||||||
|
|
@ -60,6 +68,12 @@ 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.Requests != nil {
|
||||||
|
e.Requests = make([][]byte, len(dec.Requests))
|
||||||
|
for k, v := range dec.Requests {
|
||||||
|
e.Requests[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
if dec.Override != nil {
|
if dec.Override != nil {
|
||||||
e.Override = *dec.Override
|
e.Override = *dec.Override
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ type ExecutableData struct {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||||
Deposits types.Deposits `json:"depositRequests"`
|
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,8 +107,9 @@ 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"`
|
||||||
|
Requests [][]byte `json:"executionRequests"`
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness"`
|
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobsBundleV1 struct {
|
type BlobsBundleV1 struct {
|
||||||
|
|
@ -118,9 +118,15 @@ type BlobsBundleV1 struct {
|
||||||
Blobs []hexutil.Bytes `json:"blobs"`
|
Blobs []hexutil.Bytes `json:"blobs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BlobAndProofV1 struct {
|
||||||
|
Blob hexutil.Bytes `json:"blob"`
|
||||||
|
Proof hexutil.Bytes `json:"proof"`
|
||||||
|
}
|
||||||
|
|
||||||
// JSON type overrides for ExecutionPayloadEnvelope.
|
// JSON type overrides for ExecutionPayloadEnvelope.
|
||||||
type executionPayloadEnvelopeMarshaling struct {
|
type executionPayloadEnvelopeMarshaling struct {
|
||||||
BlockValue *hexutil.Big
|
BlockValue *hexutil.Big
|
||||||
|
Requests []hexutil.Bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
type PayloadStatusV1 struct {
|
type PayloadStatusV1 struct {
|
||||||
|
|
@ -212,8 +218,8 @@ 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 data.
|
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
||||||
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
||||||
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot)
|
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +232,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
||||||
// for stateless execution, so it skips checking if the executable data hashes to
|
// for stateless execution, so it skips checking if the executable data hashes to
|
||||||
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
||||||
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
||||||
txs, err := decodeTransactions(data.Transactions)
|
txs, err := decodeTransactions(data.Transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -261,19 +267,21 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
||||||
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
||||||
withdrawalsRoot = &h
|
withdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
// Compute requestsHash if any requests are non-nil.
|
|
||||||
var (
|
var requestsHash *common.Hash
|
||||||
requestsHash *common.Hash
|
if requests != nil {
|
||||||
requests types.Requests
|
// Put back request type byte.
|
||||||
)
|
typedRequests := make([][]byte, len(requests))
|
||||||
if data.Deposits != nil {
|
for i, reqdata := range requests {
|
||||||
requests = make(types.Requests, 0)
|
typedReqdata := make([]byte, len(reqdata)+1)
|
||||||
for _, d := range data.Deposits {
|
typedReqdata[0] = byte(i)
|
||||||
requests = append(requests, types.NewRequest(d))
|
copy(typedReqdata[1:], reqdata)
|
||||||
|
typedRequests[i] = typedReqdata
|
||||||
}
|
}
|
||||||
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
h := types.CalcRequestsHash(typedRequests)
|
||||||
requestsHash = &h
|
requestsHash = &h
|
||||||
}
|
}
|
||||||
|
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: data.ParentHash,
|
ParentHash: data.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
|
@ -297,14 +305,14 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
||||||
RequestsHash: requestsHash,
|
RequestsHash: requestsHash,
|
||||||
}
|
}
|
||||||
return types.NewBlockWithHeader(header).
|
return types.NewBlockWithHeader(header).
|
||||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests}).
|
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
|
||||||
WithWitness(data.ExecutionWitness),
|
WithWitness(data.ExecutionWitness),
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
|
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar, requests [][]byte) *ExecutionPayloadEnvelope {
|
||||||
data := &ExecutableData{
|
data := &ExecutableData{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
ParentHash: block.ParentHash(),
|
ParentHash: block.ParentHash(),
|
||||||
|
|
@ -325,6 +333,8 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
ExecutionWitness: block.ExecutionWitness(),
|
ExecutionWitness: block.ExecutionWitness(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add blobs.
|
||||||
bundle := BlobsBundleV1{
|
bundle := BlobsBundleV1{
|
||||||
Commitments: make([]hexutil.Bytes, 0),
|
Commitments: make([]hexutil.Bytes, 0),
|
||||||
Blobs: make([]hexutil.Bytes, 0),
|
Blobs: make([]hexutil.Bytes, 0),
|
||||||
|
|
@ -337,30 +347,29 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
||||||
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setRequests(block.Requests(), data)
|
|
||||||
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setRequests differentiates the different request types and
|
// Remove type byte in requests.
|
||||||
// assigns them to the associated fields in ExecutableData.
|
var plainRequests [][]byte
|
||||||
func setRequests(requests types.Requests, data *ExecutableData) {
|
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
// If requests is non-nil, it means deposits are available in block and we
|
plainRequests = make([][]byte, len(requests))
|
||||||
// should return an empty slice instead of nil if there are no deposits.
|
for i, reqdata := range requests {
|
||||||
data.Deposits = make(types.Deposits, 0)
|
plainRequests[i] = reqdata[1:]
|
||||||
}
|
|
||||||
for _, r := range requests {
|
|
||||||
if d, ok := r.Inner().(*types.Deposit); ok {
|
|
||||||
data.Deposits = append(data.Deposits, d)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &ExecutionPayloadEnvelope{
|
||||||
|
ExecutionPayload: data,
|
||||||
|
BlockValue: fees,
|
||||||
|
BlobsBundle: &bundle,
|
||||||
|
Requests: plainRequests,
|
||||||
|
Override: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
|
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
|
||||||
type ExecutionPayloadBody struct {
|
type ExecutionPayloadBody struct {
|
||||||
TransactionData []hexutil.Bytes `json:"transactions"`
|
TransactionData []hexutil.Bytes `json:"transactions"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
Deposits types.Deposits `json:"depositRequests"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
|
|
|
||||||
|
|
@ -76,34 +76,32 @@ type CommitteeChain struct {
|
||||||
unixNano func() int64 // system clock (simulated clock in tests)
|
unixNano func() int64 // system clock (simulated clock in tests)
|
||||||
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
|
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
|
||||||
|
|
||||||
config *types.ChainConfig
|
config *params.ChainConfig
|
||||||
signerThreshold int
|
|
||||||
minimumUpdateScore types.UpdateScore
|
minimumUpdateScore types.UpdateScore
|
||||||
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
|
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommitteeChain creates a new CommitteeChain.
|
// NewCommitteeChain creates a new CommitteeChain.
|
||||||
func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain {
|
func NewCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain {
|
||||||
return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() })
|
return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() })
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTestCommitteeChain creates a new CommitteeChain for testing.
|
// NewTestCommitteeChain creates a new CommitteeChain for testing.
|
||||||
func NewTestCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, clock *mclock.Simulated) *CommitteeChain {
|
func NewTestCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool, clock *mclock.Simulated) *CommitteeChain {
|
||||||
return newCommitteeChain(db, config, signerThreshold, enforceTime, dummyVerifier{}, clock, func() int64 { return int64(clock.Now()) })
|
return newCommitteeChain(db, config, signerThreshold, enforceTime, dummyVerifier{}, clock, func() int64 { return int64(clock.Now()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCommitteeChain creates a new CommitteeChain with the option of replacing the
|
// newCommitteeChain creates a new CommitteeChain with the option of replacing the
|
||||||
// clock source and signature verification for testing purposes.
|
// clock source and signature verification for testing purposes.
|
||||||
func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
|
func newCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
|
||||||
s := &CommitteeChain{
|
s := &CommitteeChain{
|
||||||
committeeCache: lru.NewCache[uint64, syncCommittee](10),
|
committeeCache: lru.NewCache[uint64, syncCommittee](10),
|
||||||
db: db,
|
db: db,
|
||||||
sigVerifier: sigVerifier,
|
sigVerifier: sigVerifier,
|
||||||
clock: clock,
|
clock: clock,
|
||||||
unixNano: unixNano,
|
unixNano: unixNano,
|
||||||
config: config,
|
config: config,
|
||||||
signerThreshold: signerThreshold,
|
enforceTime: enforceTime,
|
||||||
enforceTime: enforceTime,
|
|
||||||
minimumUpdateScore: types.UpdateScore{
|
minimumUpdateScore: types.UpdateScore{
|
||||||
SignerCount: uint32(signerThreshold),
|
SignerCount: uint32(signerThreshold),
|
||||||
SubPeriodIndex: params.SyncPeriodLength / 16,
|
SubPeriodIndex: params.SyncPeriodLength / 16,
|
||||||
|
|
@ -507,7 +505,7 @@ func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time
|
||||||
if committee == nil {
|
if committee == nil {
|
||||||
return false, age, nil
|
return false, age, nil
|
||||||
}
|
}
|
||||||
if signingRoot, err := s.config.Forks.SigningRoot(head.Header); err == nil {
|
if signingRoot, err := s.config.Forks.SigningRoot(head.Header.Epoch(), head.Header.Hash()); err == nil {
|
||||||
return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil
|
return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil
|
||||||
}
|
}
|
||||||
return false, age, nil
|
return false, age, nil
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,15 @@ var (
|
||||||
testGenesis = newTestGenesis()
|
testGenesis = newTestGenesis()
|
||||||
testGenesis2 = newTestGenesis()
|
testGenesis2 = newTestGenesis()
|
||||||
|
|
||||||
tfBase = newTestForks(testGenesis, types.Forks{
|
tfBase = newTestForks(testGenesis, params.Forks{
|
||||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||||
})
|
})
|
||||||
tfAlternative = newTestForks(testGenesis, types.Forks{
|
tfAlternative = newTestForks(testGenesis, params.Forks{
|
||||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||||
&types.Fork{Epoch: 0x700, Version: []byte{1}},
|
¶ms.Fork{Epoch: 0x700, Version: []byte{1}},
|
||||||
})
|
})
|
||||||
tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{
|
tfAnotherGenesis = newTestForks(testGenesis2, params.Forks{
|
||||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||||
})
|
})
|
||||||
|
|
||||||
tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false)
|
tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false)
|
||||||
|
|
@ -226,13 +226,13 @@ type committeeChainTest struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
db *memorydb.Database
|
db *memorydb.Database
|
||||||
clock *mclock.Simulated
|
clock *mclock.Simulated
|
||||||
config types.ChainConfig
|
config params.ChainConfig
|
||||||
signerThreshold int
|
signerThreshold int
|
||||||
enforceTime bool
|
enforceTime bool
|
||||||
chain *CommitteeChain
|
chain *CommitteeChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCommitteeChainTest(t *testing.T, config types.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest {
|
func newCommitteeChainTest(t *testing.T, config params.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest {
|
||||||
c := &committeeChainTest{
|
c := &committeeChainTest{
|
||||||
t: t,
|
t: t,
|
||||||
db: memorydb.New(),
|
db: memorydb.New(),
|
||||||
|
|
@ -298,20 +298,20 @@ func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint
|
||||||
c.verifySignedHeader(tc, float64(end)+1.5, false)
|
c.verifySignedHeader(tc, float64(end)+1.5, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestGenesis() types.ChainConfig {
|
func newTestGenesis() params.ChainConfig {
|
||||||
var config types.ChainConfig
|
var config params.ChainConfig
|
||||||
rand.Read(config.GenesisValidatorsRoot[:])
|
rand.Read(config.GenesisValidatorsRoot[:])
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestForks(config types.ChainConfig, forks types.Forks) types.ChainConfig {
|
func newTestForks(config params.ChainConfig, forks params.Forks) params.ChainConfig {
|
||||||
for _, fork := range forks {
|
for _, fork := range forks {
|
||||||
config.AddFork(fork.Name, fork.Epoch, fork.Version)
|
config.AddFork(fork.Name, fork.Epoch, fork.Version)
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestCommitteeChain(parent *testCommitteeChain, config types.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain {
|
func newTestCommitteeChain(parent *testCommitteeChain, config params.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain {
|
||||||
tc := &testCommitteeChain{
|
tc := &testCommitteeChain{
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
|
|
@ -337,7 +337,7 @@ type testPeriod struct {
|
||||||
|
|
||||||
type testCommitteeChain struct {
|
type testCommitteeChain struct {
|
||||||
periods []testPeriod
|
periods []testPeriod
|
||||||
config types.ChainConfig
|
config params.ChainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testCommitteeChain) fillCommittees(begin, end int) {
|
func (tc *testCommitteeChain) fillCommittees(begin, end int) {
|
||||||
|
|
|
||||||
|
|
@ -69,12 +69,13 @@ func (h *HeadTracker) ValidatedFinality() (types.FinalityUpdate, bool) {
|
||||||
// slot or same slot and more signers) then ValidatedOptimistic is updated.
|
// slot or same slot and more signers) then ValidatedOptimistic is updated.
|
||||||
// The boolean return flag signals if ValidatedOptimistic has been changed.
|
// The boolean return flag signals if ValidatedOptimistic has been changed.
|
||||||
func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, error) {
|
func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, error) {
|
||||||
h.lock.Lock()
|
|
||||||
defer h.lock.Unlock()
|
|
||||||
|
|
||||||
if err := update.Validate(); err != nil {
|
if err := update.Validate(); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.lock.Lock()
|
||||||
|
defer h.lock.Unlock()
|
||||||
|
|
||||||
replace, err := h.validate(update.SignedHeader(), h.optimisticUpdate.SignedHeader())
|
replace, err := h.validate(update.SignedHeader(), h.optimisticUpdate.SignedHeader())
|
||||||
if replace {
|
if replace {
|
||||||
h.optimisticUpdate, h.hasOptimisticUpdate = update, true
|
h.optimisticUpdate, h.hasOptimisticUpdate = update, true
|
||||||
|
|
@ -88,12 +89,13 @@ func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, e
|
||||||
// slot or same slot and more signers) then ValidatedFinality is updated.
|
// slot or same slot and more signers) then ValidatedFinality is updated.
|
||||||
// The boolean return flag signals if ValidatedFinality has been changed.
|
// The boolean return flag signals if ValidatedFinality has been changed.
|
||||||
func (h *HeadTracker) ValidateFinality(update types.FinalityUpdate) (bool, error) {
|
func (h *HeadTracker) ValidateFinality(update types.FinalityUpdate) (bool, error) {
|
||||||
h.lock.Lock()
|
|
||||||
defer h.lock.Unlock()
|
|
||||||
|
|
||||||
if err := update.Validate(); err != nil {
|
if err := update.Validate(); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.lock.Lock()
|
||||||
|
defer h.lock.Unlock()
|
||||||
|
|
||||||
replace, err := h.validate(update.SignedHeader(), h.finalityUpdate.SignedHeader())
|
replace, err := h.validate(update.SignedHeader(), h.finalityUpdate.SignedHeader())
|
||||||
if replace {
|
if replace {
|
||||||
h.finalityUpdate, h.hasFinalityUpdate = update, true
|
h.finalityUpdate, h.hasFinalityUpdate = update, true
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func GenerateTestCommittee() *types.SerializedSyncCommittee {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate {
|
func GenerateTestUpdate(config *params.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate {
|
||||||
update := new(types.LightClientUpdate)
|
update := new(types.LightClientUpdate)
|
||||||
update.NextSyncCommitteeRoot = nextCommittee.Root()
|
update.NextSyncCommitteeRoot = nextCommittee.Root()
|
||||||
var attestedHeader types.Header
|
var attestedHeader types.Header
|
||||||
|
|
@ -48,9 +48,9 @@ func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nex
|
||||||
return update
|
return update
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateTestSignedHeader(header types.Header, config *types.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader {
|
func GenerateTestSignedHeader(header types.Header, config *params.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader {
|
||||||
bitmask := makeBitmask(signerCount)
|
bitmask := makeBitmask(signerCount)
|
||||||
signingRoot, _ := config.Forks.SigningRoot(header)
|
signingRoot, _ := config.Forks.SigningRoot(header.Epoch(), header.Hash())
|
||||||
c, _ := dummyVerifier{}.deserializeSyncCommittee(committee)
|
c, _ := dummyVerifier{}.deserializeSyncCommittee(committee)
|
||||||
return types.SignedHeader{
|
return types.SignedHeader{
|
||||||
Header: header,
|
Header: header,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package types
|
package params
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
@ -39,81 +39,13 @@ const syncCommitteeDomain = 7
|
||||||
|
|
||||||
var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"}
|
var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"}
|
||||||
|
|
||||||
// Fork describes a single beacon chain fork and also stores the calculated
|
// ClientConfig contains beacon light client configuration.
|
||||||
// signature domain used after this fork.
|
type ClientConfig struct {
|
||||||
type Fork struct {
|
ChainConfig
|
||||||
// Name of the fork in the chain config (config.yaml) file
|
Apis []string
|
||||||
Name string
|
CustomHeader map[string]string
|
||||||
|
Threshold int
|
||||||
// Epoch when given fork version is activated
|
NoFilter bool
|
||||||
Epoch uint64
|
|
||||||
|
|
||||||
// Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types
|
|
||||||
Version []byte
|
|
||||||
|
|
||||||
// index in list of known forks or MaxInt if unknown
|
|
||||||
knownIndex int
|
|
||||||
|
|
||||||
// calculated by computeDomain, based on fork version and genesis validators root
|
|
||||||
domain merkle.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// computeDomain returns the signature domain based on the given fork version
|
|
||||||
// and genesis validator set root.
|
|
||||||
func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) {
|
|
||||||
var (
|
|
||||||
hasher = sha256.New()
|
|
||||||
forkVersion32 merkle.Value
|
|
||||||
forkDataRoot merkle.Value
|
|
||||||
)
|
|
||||||
copy(forkVersion32[:], f.Version)
|
|
||||||
hasher.Write(forkVersion32[:])
|
|
||||||
hasher.Write(genesisValidatorsRoot[:])
|
|
||||||
hasher.Sum(forkDataRoot[:0])
|
|
||||||
|
|
||||||
f.domain[0] = syncCommitteeDomain
|
|
||||||
copy(f.domain[4:], forkDataRoot[:28])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forks is the list of all beacon chain forks in the chain configuration.
|
|
||||||
type Forks []*Fork
|
|
||||||
|
|
||||||
// domain returns the signature domain for the given epoch (assumes that domains
|
|
||||||
// have already been calculated).
|
|
||||||
func (f Forks) domain(epoch uint64) (merkle.Value, error) {
|
|
||||||
for i := len(f) - 1; i >= 0; i-- {
|
|
||||||
if epoch >= f[i].Epoch {
|
|
||||||
return f[i].domain, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SigningRoot calculates the signing root of the given header.
|
|
||||||
func (f Forks) SigningRoot(header Header) (common.Hash, error) {
|
|
||||||
domain, err := f.domain(header.Epoch())
|
|
||||||
if err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
signingRoot common.Hash
|
|
||||||
headerHash = header.Hash()
|
|
||||||
hasher = sha256.New()
|
|
||||||
)
|
|
||||||
hasher.Write(headerHash[:])
|
|
||||||
hasher.Write(domain[:])
|
|
||||||
hasher.Sum(signingRoot[:0])
|
|
||||||
|
|
||||||
return signingRoot, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Forks) Len() int { return len(f) }
|
|
||||||
func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
|
||||||
func (f Forks) Less(i, j int) bool {
|
|
||||||
if f[i].Epoch != f[j].Epoch {
|
|
||||||
return f[i].Epoch < f[j].Epoch
|
|
||||||
}
|
|
||||||
return f[i].knownIndex < f[j].knownIndex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainConfig contains the beacon chain configuration.
|
// ChainConfig contains the beacon chain configuration.
|
||||||
|
|
@ -121,6 +53,7 @@ type ChainConfig struct {
|
||||||
GenesisTime uint64 // Unix timestamp of slot 0
|
GenesisTime uint64 // Unix timestamp of slot 0
|
||||||
GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation
|
GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation
|
||||||
Forks Forks
|
Forks Forks
|
||||||
|
Checkpoint common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForkAtEpoch returns the latest active fork at the given epoch.
|
// ForkAtEpoch returns the latest active fork at the given epoch.
|
||||||
|
|
@ -202,3 +135,79 @@ func (c *ChainConfig) LoadForks(path string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fork describes a single beacon chain fork and also stores the calculated
|
||||||
|
// signature domain used after this fork.
|
||||||
|
type Fork struct {
|
||||||
|
// Name of the fork in the chain config (config.yaml) file
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Epoch when given fork version is activated
|
||||||
|
Epoch uint64
|
||||||
|
|
||||||
|
// Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types
|
||||||
|
Version []byte
|
||||||
|
|
||||||
|
// index in list of known forks or MaxInt if unknown
|
||||||
|
knownIndex int
|
||||||
|
|
||||||
|
// calculated by computeDomain, based on fork version and genesis validators root
|
||||||
|
domain merkle.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDomain returns the signature domain based on the given fork version
|
||||||
|
// and genesis validator set root.
|
||||||
|
func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) {
|
||||||
|
var (
|
||||||
|
hasher = sha256.New()
|
||||||
|
forkVersion32 merkle.Value
|
||||||
|
forkDataRoot merkle.Value
|
||||||
|
)
|
||||||
|
copy(forkVersion32[:], f.Version)
|
||||||
|
hasher.Write(forkVersion32[:])
|
||||||
|
hasher.Write(genesisValidatorsRoot[:])
|
||||||
|
hasher.Sum(forkDataRoot[:0])
|
||||||
|
|
||||||
|
f.domain[0] = syncCommitteeDomain
|
||||||
|
copy(f.domain[4:], forkDataRoot[:28])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forks is the list of all beacon chain forks in the chain configuration.
|
||||||
|
type Forks []*Fork
|
||||||
|
|
||||||
|
// domain returns the signature domain for the given epoch (assumes that domains
|
||||||
|
// have already been calculated).
|
||||||
|
func (f Forks) domain(epoch uint64) (merkle.Value, error) {
|
||||||
|
for i := len(f) - 1; i >= 0; i-- {
|
||||||
|
if epoch >= f[i].Epoch {
|
||||||
|
return f[i].domain, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SigningRoot calculates the signing root of the given header.
|
||||||
|
func (f Forks) SigningRoot(epoch uint64, root common.Hash) (common.Hash, error) {
|
||||||
|
domain, err := f.domain(epoch)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
signingRoot common.Hash
|
||||||
|
hasher = sha256.New()
|
||||||
|
)
|
||||||
|
hasher.Write(root[:])
|
||||||
|
hasher.Write(domain[:])
|
||||||
|
hasher.Sum(signingRoot[:0])
|
||||||
|
|
||||||
|
return signingRoot, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Forks) Len() int { return len(f) }
|
||||||
|
func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
||||||
|
func (f Forks) Less(i, j int) bool {
|
||||||
|
if f[i].Epoch != f[j].Epoch {
|
||||||
|
return f[i].Epoch < f[j].Epoch
|
||||||
|
}
|
||||||
|
return f[i].knownIndex < f[j].knownIndex
|
||||||
|
}
|
||||||
56
beacon/params/networks.go
Normal file
56
beacon/params/networks.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MainnetLightConfig = (&ChainConfig{
|
||||||
|
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
||||||
|
GenesisTime: 1606824023,
|
||||||
|
Checkpoint: common.HexToHash("0x6509b691f4de4f7b083f2784938fd52f0e131675432b3fd85ea549af9aebd3d0"),
|
||||||
|
}).
|
||||||
|
AddFork("GENESIS", 0, []byte{0, 0, 0, 0}).
|
||||||
|
AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}).
|
||||||
|
AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}).
|
||||||
|
AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}).
|
||||||
|
AddFork("DENEB", 269568, []byte{4, 0, 0, 0})
|
||||||
|
|
||||||
|
SepoliaLightConfig = (&ChainConfig{
|
||||||
|
GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"),
|
||||||
|
GenesisTime: 1655733600,
|
||||||
|
Checkpoint: common.HexToHash("0x456e85f5608afab3465a0580bff8572255f6d97af0c5f939e3f7536b5edb2d3f"),
|
||||||
|
}).
|
||||||
|
AddFork("GENESIS", 0, []byte{144, 0, 0, 105}).
|
||||||
|
AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}).
|
||||||
|
AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}).
|
||||||
|
AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}).
|
||||||
|
AddFork("DENEB", 132608, []byte{144, 0, 0, 115})
|
||||||
|
|
||||||
|
HoleskyLightConfig = (&ChainConfig{
|
||||||
|
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
||||||
|
GenesisTime: 1695902400,
|
||||||
|
Checkpoint: common.HexToHash("0x6456a1317f54d4b4f2cb5bc9d153b5af0988fe767ef0609f0236cf29030bcff7"),
|
||||||
|
}).
|
||||||
|
AddFork("GENESIS", 0, []byte{1, 1, 112, 0}).
|
||||||
|
AddFork("ALTAIR", 0, []byte{2, 1, 112, 0}).
|
||||||
|
AddFork("BELLATRIX", 0, []byte{3, 1, 112, 0}).
|
||||||
|
AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}).
|
||||||
|
AddFork("DENEB", 29696, []byte{5, 1, 112, 0})
|
||||||
|
)
|
||||||
|
|
@ -5,88 +5,88 @@
|
||||||
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
||||||
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
||||||
|
|
||||||
# version:golang 1.23.1
|
# version:golang 1.23.3
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
6ee44e298379d146a5e5aa6b1c5b5d5f5d0a3365eabdd70741e6e21340ec3b0d go1.23.1.src.tar.gz
|
8d6a77332487557c6afa2421131b50f83db4ae3c579c3bc72e670ee1f6968599 go1.23.3.src.tar.gz
|
||||||
f17f2791717c15728ec63213a014e244c35f9c8846fb29f5a1b63d0c0556f756 go1.23.1.aix-ppc64.tar.gz
|
bdbf2a243ed4a121c9988684e5b15989cb244c1ff9e41ca823d0187b5c859114 go1.23.3.aix-ppc64.tar.gz
|
||||||
dd9e772686ed908bcff94b6144322d4e2473a7dcd7c696b7e8b6d12f23c887fd go1.23.1.darwin-amd64.pkg
|
b79c77bbdf61e6e486aa6bea9286f3f7969c28e2ff7686ce10c334f746bfb724 go1.23.3.darwin-amd64.pkg
|
||||||
488d9e4ca3e3ed513ee4edd91bef3a2360c65fa6d6be59cf79640bf840130a58 go1.23.1.darwin-amd64.tar.gz
|
c7e024d5c0bc81845070f23598caf02f05b8ae88fd4ad2cd3e236ddbea833ad2 go1.23.3.darwin-amd64.tar.gz
|
||||||
be34b488157ec69d94e26e1554558219a2c90789bcb7e3686965a7f9c8cfcbe7 go1.23.1.darwin-arm64.pkg
|
3e764df0db8f3c7470b9ff641954a380510a4822613c06bd5a195fd083f4731d go1.23.3.darwin-arm64.pkg
|
||||||
e223795ca340e285a760a6446ce57a74500b30e57469a4109961d36184d3c05a go1.23.1.darwin-arm64.tar.gz
|
31e119fe9bde6e105407a32558d5b5fa6ca11e2bd17f8b7b2f8a06aba16a0632 go1.23.3.darwin-arm64.tar.gz
|
||||||
6af626176923a6ae6c5de6dc1c864f38365793c0e4ecd0d6eab847bdc23953e5 go1.23.1.dragonfly-amd64.tar.gz
|
3872c9a98331050a242afe63fa6abc8fc313aca83dcaefda318e903309ac0c8d go1.23.3.dragonfly-amd64.tar.gz
|
||||||
cc957c1a019702e6cdc2e257202d42799011ebc1968b6c3bcd6b1965952607d5 go1.23.1.freebsd-386.tar.gz
|
69479fa016ec5b4605885643ce0c2dd5c583e02353978feb6de38c961863b9cc go1.23.3.freebsd-386.tar.gz
|
||||||
a7d57781c50bb80886a8f04066791956d45aa3eea0f83070c5268b6223afb2ff go1.23.1.freebsd-amd64.tar.gz
|
bf1de22a900646ef4f79480ed88337856d47089cc610f87e6fef46f6b8db0e1f go1.23.3.freebsd-amd64.tar.gz
|
||||||
c7b09f3fef456048e596db9bea746eb66796aeb82885622b0388feee18f36a3e go1.23.1.freebsd-arm.tar.gz
|
e461f866479bc36bdd4cfec32bfecb1bb243152268a1b3223de109410dec3407 go1.23.3.freebsd-arm.tar.gz
|
||||||
b05cd6a77995a0c8439d88df124811c725fb78b942d0b6dd1643529d7ba62f1f go1.23.1.freebsd-arm64.tar.gz
|
24154b4018a45540aefeb6b5b9ffdcc8d9a8cdb78cd7fec262787b89fed19997 go1.23.3.freebsd-arm64.tar.gz
|
||||||
56236ae70be1613f2915943b94f53c96be5bffc0719314078facd778a89bc57e go1.23.1.freebsd-riscv64.tar.gz
|
218f3f1532e61dd65c330c2a5fc85bec18cc3690489763e62ffa9bb9fc85a68e go1.23.3.freebsd-riscv64.tar.gz
|
||||||
8644c52df4e831202114fd67c9fcaf1f7233ad27bf945ac53fa7217cf1a0349f go1.23.1.illumos-amd64.tar.gz
|
24e3f34858b8687c31f5e5ab9e46d27fb613b0d50a94261c500cebb2d79c0672 go1.23.3.illumos-amd64.tar.gz
|
||||||
cdee2f4e2efa001f7ee75c90f2efc310b63346cfbba7b549987e9139527c6b17 go1.23.1.linux-386.tar.gz
|
3d7b00191a43c50d28e0903a0c576104bc7e171a8670de419d41111c08dfa299 go1.23.3.linux-386.tar.gz
|
||||||
49bbb517cfa9eee677e1e7897f7cf9cfdbcf49e05f61984a2789136de359f9bd go1.23.1.linux-amd64.tar.gz
|
a0afb9744c00648bafb1b90b4aba5bdb86f424f02f9275399ce0c20b93a2c3a8 go1.23.3.linux-amd64.tar.gz
|
||||||
faec7f7f8ae53fda0f3d408f52182d942cc89ef5b7d3d9f23ff117437d4b2d2f go1.23.1.linux-arm64.tar.gz
|
1f7cbd7f668ea32a107ecd41b6488aaee1f5d77a66efd885b175494439d4e1ce go1.23.3.linux-arm64.tar.gz
|
||||||
6c7832c7dcd8fb6d4eb308f672a725393403c74ee7be1aeccd8a443015df99de go1.23.1.linux-armv6l.tar.gz
|
5f0332754beffc65af65a7b2da76e9dd997567d0d81b6f4f71d3588dc7b4cb00 go1.23.3.linux-armv6l.tar.gz
|
||||||
649ce3856ddc808c00b14a46232eab0bf95e7911cdf497010b17d76656f5ca4e go1.23.1.linux-loong64.tar.gz
|
1d0161a8946c7d99f717bad23631738408511f9f87e78d852224a023d8882ad8 go1.23.3.linux-loong64.tar.gz
|
||||||
201911048f234e5a0c51ec94b1a11d4e47062fee4398b1d2faa6c820dc026724 go1.23.1.linux-mips.tar.gz
|
e924a7c9027f521f8a3563541ed0f89a4db3ef005b6b71263415b38e0b46e63a go1.23.3.linux-mips.tar.gz
|
||||||
2bce3743df463915e45d2612f9476ffb03d0b3750b1cb3879347de08715b5fc6 go1.23.1.linux-mips64.tar.gz
|
4cdf8c38165627f032c2b17cdd95e4aafff40d75fc873824d4c94914284098ca go1.23.3.linux-mips64.tar.gz
|
||||||
54e301f266e33431b0703136e0bbd4cf02461b1ecedd37b7cbd90cb862a98e5f go1.23.1.linux-mips64le.tar.gz
|
5e49347e7325d2e268fb14040529b704e66eed77154cc73a919e9167d8527a2f go1.23.3.linux-mips64le.tar.gz
|
||||||
8efd495e93d17408c0803595cdc3bf13cb28e0f957aeabd9cc18245fb8e64019 go1.23.1.linux-mipsle.tar.gz
|
142eabc17cee99403e895383ed7a6b7b40e740e8c2f73b79352bb9d1242fbd98 go1.23.3.linux-mipsle.tar.gz
|
||||||
52bd68689095831ad9af7160844c23b28bb8d0acd268de7e300ff5f0662b7a07 go1.23.1.linux-ppc64.tar.gz
|
96ad61ba6b6cc0f5adfd75e65231c61e7db26d8236f01117023899528164d1b0 go1.23.3.linux-ppc64.tar.gz
|
||||||
042888cae54b5fbfd9dd1e3b6bc4a5134879777fe6497fc4c62ec394b5ecf2da go1.23.1.linux-ppc64le.tar.gz
|
e3b926c81e8099d3cee6e6e270b85b39c3bd44263f8d3df29aacb4d7e00507c8 go1.23.3.linux-ppc64le.tar.gz
|
||||||
1a4a609f0391bea202d9095453cbfaf7368fa88a04c206bf9dd715a738664dc3 go1.23.1.linux-riscv64.tar.gz
|
324e03b6f59be841dfbaeabc466224b0f0905f5ad3a225b7c0703090e6c4b1a5 go1.23.3.linux-riscv64.tar.gz
|
||||||
47dc49ad45c45e192efa0df7dc7bc5403f5f2d15b5d0dc74ef3018154b616f4d go1.23.1.linux-s390x.tar.gz
|
6bd72fcef72b046b6282c2d1f2c38f31600e4fe9361fcd8341500c754fb09c38 go1.23.3.linux-s390x.tar.gz
|
||||||
fbfbd5efa6a5d581ea7f5e65015f927db0e52135cab057e43d39d5482da54b61 go1.23.1.netbsd-386.tar.gz
|
5df382337fe2e4ea6adaafa823da5e083513a97534a38f89d691dd6f599084ca go1.23.3.netbsd-386.tar.gz
|
||||||
e96e1cc5cf36113ee6099d1a7306b22cd9c3f975a36bdff954c59f104f22b853 go1.23.1.netbsd-amd64.tar.gz
|
9ae7cb6095a3e91182ac03547167e230fddd4941ed02dbdb6af663b2a53d9db7 go1.23.3.netbsd-amd64.tar.gz
|
||||||
c394dfc06bfc276a591209a37e09cd39089ec9a9cc3db30b94814ce2e39eb1d4 go1.23.1.netbsd-arm.tar.gz
|
4a452c4134a9bea6213d8925d322f26b01c0eccda1330585bb2b241c76a0c3ea go1.23.3.netbsd-arm.tar.gz
|
||||||
b3b35d64f32821a68b3e2994032dbefb81978f2ec3f218c7a770623b82d36b8e go1.23.1.netbsd-arm64.tar.gz
|
8ff3b5184d840148dbca061c04dca35a7070dc894255d3b755066bd76a7094dc go1.23.3.netbsd-arm64.tar.gz
|
||||||
3c775c4c16c182e33c2c4ac090d9a247a93b3fb18a3df01d87d490f29599faff go1.23.1.openbsd-386.tar.gz
|
5b6940922e68ac1162a704a8b583fb4f039f955bfe97c35a56c40269cbcff9b1 go1.23.3.openbsd-386.tar.gz
|
||||||
5edbe53b47c57b32707fd7154536fbe9eaa79053fea01650c93b54cdba13fc0f go1.23.1.openbsd-amd64.tar.gz
|
6ae4aeb6a88f3754b10ecec90422a30fb8bf86c3187be2be9408d67a5a235ace go1.23.3.openbsd-amd64.tar.gz
|
||||||
c30903dd8fa98b8aca8e9db0962ce9f55502aed93e0ef41e5ae148aaa0088de1 go1.23.1.openbsd-arm.tar.gz
|
e5eae226391b60c4d1ea1022663f55b225c6d7bab67f31fbafd5dd7a04684006 go1.23.3.openbsd-arm.tar.gz
|
||||||
12da183489e58f9c6b357bc1b626f85ed7d4220cab31a49d6a49e6ac6a718b67 go1.23.1.openbsd-arm64.tar.gz
|
e12b2c04535e0bf5561d54831122b410d708519c1ec2c56b0c2350b15243c331 go1.23.3.openbsd-arm64.tar.gz
|
||||||
9cc9aad37696a4a10c31dcec9e35a308de0b369dad354d54cf07406ac6fa7c6f go1.23.1.openbsd-ppc64.tar.gz
|
599818e4062166d7a112f6f3fcca2dd4e2cdd3111fe48f9757bd8debf38c7f52 go1.23.3.openbsd-ppc64.tar.gz
|
||||||
e1d740dda062ce5a276a0c3ed7d8b6353238bc8ff405f63e2e3480bfd26a5ec5 go1.23.1.openbsd-riscv64.tar.gz
|
9ca4db8cab2a07d561f5b2a9397793684ab3b22326add1fe8cda8a545a1693db go1.23.3.openbsd-riscv64.tar.gz
|
||||||
da2a37f9987f01f096859230aa13ecc4ad2e7884465bce91004bc78c64435d65 go1.23.1.plan9-386.tar.gz
|
8fca1ec2aced936e0170605378ee7f0acb38f002490321f67fc83728ee281967 go1.23.3.plan9-386.tar.gz
|
||||||
fd8fff8b0697d55c4a4d02a8dc998192b80a9dc2a057647373d6ff607cad29de go1.23.1.plan9-amd64.tar.gz
|
22d663692224fc1933a97f61d9fe49815e3b9ef1c2be97046505683fdf2e23c7 go1.23.3.plan9-amd64.tar.gz
|
||||||
52efbc5804c1c86ba7868aa8ebbc31cc8c2a27b62a60fd57944970d48fc67525 go1.23.1.plan9-arm.tar.gz
|
d0417a702d0e776d57e450fa2ce1ce7efa199a636644776862dbf946c409a462 go1.23.3.plan9-arm.tar.gz
|
||||||
f54205f21e2143f2ada1bf1c00ddf64590f5139d5c3fb77cc06175f0d8cc7567 go1.23.1.solaris-amd64.tar.gz
|
b5d9db1c02e0ca266a142eb687bd7749890c30872b09a4a0ffcd491425039754 go1.23.3.solaris-amd64.tar.gz
|
||||||
369a17f0cfd29e5c848e58ffe0d772da20abe334d1c7ca01dbcd55bb3db0b440 go1.23.1.windows-386.msi
|
14b7baf4af2046013b74dfac6e9a0a7403f15ee9940a16890bc028dfd32c49ac go1.23.3.windows-386.msi
|
||||||
ab866f47d7be56e6b1c67f1d529bf4c23331a339fb0785f435a0552d352cb257 go1.23.1.windows-386.zip
|
23da9089ea6c5612d718f13c26e9bfc9aaaabe222838075346a8191d48f9dfe5 go1.23.3.windows-386.zip
|
||||||
e99dac215ee437b9bb8f8b14bbfe0e8756882c1ed291f30818e8363bc9c047a5 go1.23.1.windows-amd64.msi
|
614f0e3eed82245dfb4356d4e8d5b96abecca6a4c4f0168c0e389e4dd6284db8 go1.23.3.windows-amd64.msi
|
||||||
32dedf277c86610e380e1765593edb66876f00223df71690bd6be68ee17675c0 go1.23.1.windows-amd64.zip
|
81968b563642096b8a7521171e2be6e77ff6f44032f7493b7bdec9d33f44f31d go1.23.3.windows-amd64.zip
|
||||||
23169c79dc6b54e0dffb25be6b67425ad9759392a58309bc057430a9bf4c8f6a go1.23.1.windows-arm.msi
|
c9951eecad732c59dfde6dc4803fa9253eb074663c61035c8d856f4d2eb146cb go1.23.3.windows-arm.msi
|
||||||
1a57615a09f13534f88e9f2d7efd5743535d1a5719b19e520eef965a634f8efb go1.23.1.windows-arm.zip
|
1a7db02be47deada42082d21d63eba0013f93375cfa0e7768962f1295a469022 go1.23.3.windows-arm.zip
|
||||||
313e1a543931ad8735b4df8969e00f5f4c2ef07be21f54015ede961a70263d35 go1.23.1.windows-arm64.msi
|
a74e3e195219af4330b93c71cd4b736b709a5654a07cc37eebe181c4984afb82 go1.23.3.windows-arm64.msi
|
||||||
64ad0954d2c33f556fb1018d62de091254aa6e3a94f1c8a8b16af0d3701d194e go1.23.1.windows-arm64.zip
|
dbdfa868b1a3f8c62950373e4975d83f90dd8b869a3907319af8384919bcaffe go1.23.3.windows-arm64.zip
|
||||||
|
|
||||||
# version:golangci 1.59.0
|
# version:golangci 1.61.0
|
||||||
# https://github.com/golangci/golangci-lint/releases/
|
# https://github.com/golangci/golangci-lint/releases/
|
||||||
# https://github.com/golangci/golangci-lint/releases/download/v1.59.0/
|
# https://github.com/golangci/golangci-lint/releases/download/v1.61.0/
|
||||||
418acf7e255ddc0783e97129c9b03d9311b77826a5311d425a01c708a86417e7 golangci-lint-1.59.0-darwin-amd64.tar.gz
|
5c280ef3284f80c54fd90d73dc39ca276953949da1db03eb9dd0fbf868cc6e55 golangci-lint-1.61.0-darwin-amd64.tar.gz
|
||||||
5f6a1d95a6dd69f6e328eb56dd311a38e04cfab79a1305fbf4957f4e203f47b6 golangci-lint-1.59.0-darwin-arm64.tar.gz
|
544334890701e4e04a6e574bc010bea8945205c08c44cced73745a6378012d36 golangci-lint-1.61.0-darwin-arm64.tar.gz
|
||||||
8899bf589185d49f747f3e5db9f0bde8a47245a100c64a3dd4d65e8e92cfc4f2 golangci-lint-1.59.0-freebsd-386.tar.gz
|
e885a6f561092055930ebd298914d80e8fd2e10d2b1e9942836c2c6a115301fa golangci-lint-1.61.0-freebsd-386.tar.gz
|
||||||
658212f138d9df2ac89427e22115af34bf387c0871d70f2a25101718946a014f golangci-lint-1.59.0-freebsd-amd64.tar.gz
|
b13f6a3f11f65e7ff66b734d7554df3bbae0f485768848424e7554ed289e19c2 golangci-lint-1.61.0-freebsd-amd64.tar.gz
|
||||||
4c6395ea40f314d3b6fa17d8997baab93464d5d1deeaab513155e625473bd03a golangci-lint-1.59.0-freebsd-armv6.tar.gz
|
cd8e7bbe5b8f33ed1597aa1cc588da96a3b9f22e1b9ae60d93511eae1a0ee8c5 golangci-lint-1.61.0-freebsd-armv6.tar.gz
|
||||||
ff37da4fbaacdb6bbae70fdbdbb1ba932a859956f788c82822fa06bef5b7c6b3 golangci-lint-1.59.0-freebsd-armv7.tar.gz
|
7ade524dbd88bd250968f45e190af90e151fa5ee63dd6aa7f7bb90e8155db61d golangci-lint-1.61.0-freebsd-armv7.tar.gz
|
||||||
439739469ed2bda182b1ec276d40c40e02f195537f78e3672996741ad223d6b6 golangci-lint-1.59.0-illumos-amd64.tar.gz
|
0fe3cd8a1ed8d9f54f48670a5af3df056d6040d94017057f0f4d65c930660ad9 golangci-lint-1.61.0-illumos-amd64.tar.gz
|
||||||
940801d46790e40d0a097d8fee34e2606f0ef148cd039654029b0b8750a15ed6 golangci-lint-1.59.0-linux-386.tar.gz
|
b463fc5053a612abd26393ebaff1d85d7d56058946f4f0f7bf25ed44ea899415 golangci-lint-1.61.0-linux-386.tar.gz
|
||||||
3b14a439f33c4fff83dbe0349950d984042b9a1feb6c62f82787b598fc3ab5f4 golangci-lint-1.59.0-linux-amd64.tar.gz
|
77cb0af99379d9a21d5dc8c38364d060e864a01bd2f3e30b5e8cc550c3a54111 golangci-lint-1.61.0-linux-amd64.tar.gz
|
||||||
c57e6c0b0fa03089a2611dceddd5bc5d206716cccdff8b149da8baac598719a1 golangci-lint-1.59.0-linux-arm64.tar.gz
|
af60ac05566d9351615cb31b4cc070185c25bf8cbd9b09c1873aa5ec6f3cc17e golangci-lint-1.61.0-linux-arm64.tar.gz
|
||||||
93149e2d3b25ac754df9a23172403d8aa6d021a7e0d9c090a12f51897f68c9a0 golangci-lint-1.59.0-linux-armv6.tar.gz
|
1f307f2fcc5d7d674062a967a0d83a7091e300529aa237ec6ad2b3dd14c897f5 golangci-lint-1.61.0-linux-armv6.tar.gz
|
||||||
d10ac38239d9efee3ee87b55c96cdf3fa09e1a525babe3ffdaaf65ccc48cf3dc golangci-lint-1.59.0-linux-armv7.tar.gz
|
3ad8cbaae75a547450844811300f99c4cd290277398e43d22b9eb1792d15af4c golangci-lint-1.61.0-linux-armv7.tar.gz
|
||||||
047338114b4f0d5f08f0fb9a397b03cc171916ed0960be7dfb355c2320cd5e9c golangci-lint-1.59.0-linux-loong64.tar.gz
|
9be2ca67d961d7699079739cf6f7c8291c5183d57e34d1677de21ca19d0bd3ed golangci-lint-1.61.0-linux-loong64.tar.gz
|
||||||
5632df0f7f8fc03a80a266130faef0b5902d280cf60621f1b2bdc1aef6d97ee9 golangci-lint-1.59.0-linux-mips64.tar.gz
|
90d005e1648115ebf0861b408eab9c936079a24763e883058b0a227cd3135d31 golangci-lint-1.61.0-linux-mips64.tar.gz
|
||||||
71dd638c82fa4439171e7126d2c7a32b5d103bfdef282cea40c83632cb3d1f4b golangci-lint-1.59.0-linux-mips64le.tar.gz
|
6d2ed4f49407115460b8c10ccfc40fd177e0887a48864a2879dd16e84ba2a48c golangci-lint-1.61.0-linux-mips64le.tar.gz
|
||||||
6cf9ea0d34e91669948483f9ae7f07da319a879344373a1981099fbd890cde00 golangci-lint-1.59.0-linux-ppc64le.tar.gz
|
633089589af5a58b7430afb6eee107d4e9c99e8d91711ddc219eb13a07e8d3b8 golangci-lint-1.61.0-linux-ppc64le.tar.gz
|
||||||
af0205fa6fbab197cee613c359947711231739095d21b5c837086233b36ad971 golangci-lint-1.59.0-linux-riscv64.tar.gz
|
4c1a097d9e0d1b4a8144dae6a1f5583a38d662f3bdc1498c4e954b6ed856be98 golangci-lint-1.61.0-linux-riscv64.tar.gz
|
||||||
a9d2fb93f3c688ebccef94f5dc96c0b07c4d20bf6556cddebd8442159b0c80f6 golangci-lint-1.59.0-linux-s390x.tar.gz
|
30581d3c987d287b7064617f1a2694143e10dffc40bc25be6636006ee82d7e1c golangci-lint-1.61.0-linux-s390x.tar.gz
|
||||||
68ab4c57a847b8ace9679887f2f8b2b6760e57ee29dcde8c3f40dd8bb2654fa2 golangci-lint-1.59.0-netbsd-386.tar.gz
|
42530bf8100bd43c07f5efe6d92148ba6c5a7a712d510c6f24be85af6571d5eb golangci-lint-1.61.0-netbsd-386.tar.gz
|
||||||
d277b8b435c19406d00de4d509eadf5a024a5782878332e9a1b7c02bb76e87a7 golangci-lint-1.59.0-netbsd-amd64.tar.gz
|
b8bb07c920f6601edf718d5e82ec0784fd590b0992b42b6ec18da99f26013ed4 golangci-lint-1.61.0-netbsd-amd64.tar.gz
|
||||||
83211656be8dcfa1545af4f92894409f412d1f37566798cb9460a526593ad62c golangci-lint-1.59.0-netbsd-arm64.tar.gz
|
353a51527c60bd0776b0891b03f247c791986f625fca689d121972c624e54198 golangci-lint-1.61.0-netbsd-arm64.tar.gz
|
||||||
6c6866d28bf79fa9817a0f7d2b050890ed109cae80bdb4dfa39536a7226da237 golangci-lint-1.59.0-netbsd-armv6.tar.gz
|
957a6272c3137910514225704c5dac0723b9c65eb7d9587366a997736e2d7580 golangci-lint-1.61.0-netbsd-armv6.tar.gz
|
||||||
11587566363bd03ca586b7df9776ccaed569fcd1f3489930ac02f9375b307503 golangci-lint-1.59.0-netbsd-armv7.tar.gz
|
a89eb28ff7f18f5cd52b914739360fa95cf2f643de4adeca46e26bec3a07e8d8 golangci-lint-1.61.0-netbsd-armv7.tar.gz
|
||||||
466181a8967bafa495e41494f93a0bec829c2cf715de874583b0460b3b8ae2b8 golangci-lint-1.59.0-windows-386.zip
|
d8d74c43600b271393000717a4ed157d7a15bb85bab7db2efad9b63a694d4634 golangci-lint-1.61.0-windows-386.zip
|
||||||
3317d8a87a99a49a0a1321d295c010790e6dbf43ee96b318f4b8bb23eae7a565 golangci-lint-1.59.0-windows-amd64.zip
|
e7bc2a81929a50f830244d6d2e657cce4f19a59aff49fa9000176ff34fda64ce golangci-lint-1.61.0-windows-amd64.zip
|
||||||
b3af955c7fceac8220a36fc799e1b3f19d3b247d32f422caac5f9845df8f7316 golangci-lint-1.59.0-windows-arm64.zip
|
ed97c221596dd771e3dd9344872c140340bee2e819cd7a90afa1de752f1f2e0f golangci-lint-1.61.0-windows-arm64.zip
|
||||||
6f083c7d0c764e5a0e5bde46ee3e91ae357d80c194190fe1d9754392e9064c7e golangci-lint-1.59.0-windows-armv6.zip
|
4b365233948b13d02d45928a5c390045e00945e919747b9887b5f260247541ae golangci-lint-1.61.0-windows-armv6.zip
|
||||||
3709b4dd425deadab27748778d08e03c0f804d7748f7dd5b6bb488d98aa031c7 golangci-lint-1.59.0-windows-armv7.zip
|
595538fb64d152173959d28f6235227f9cd969a828e5af0c4e960d02af4ffd0e golangci-lint-1.61.0-windows-armv7.zip
|
||||||
|
|
||||||
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
||||||
#
|
#
|
||||||
|
|
|
||||||
246
build/ci.go
246
build/ci.go
|
|
@ -24,9 +24,14 @@ Usage: go run build/ci.go <command> <command flags/arguments>
|
||||||
|
|
||||||
Available commands are:
|
Available commands are:
|
||||||
|
|
||||||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
lint -- runs certain pre-selected linters
|
||||||
test [ -coverage ] [ packages... ] -- runs the tests
|
check_tidy -- verifies that everything is 'go mod tidy'-ed
|
||||||
lint -- runs certain pre-selected linters
|
check_generate -- verifies that everything is 'go generate'-ed
|
||||||
|
check_baddeps -- verifies that certain dependencies are avoided
|
||||||
|
|
||||||
|
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||||
|
test [ -coverage ] [ packages... ] -- runs the tests
|
||||||
|
|
||||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
||||||
importkeys -- imports signing keys from env
|
importkeys -- imports signing keys from env
|
||||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||||
|
|
@ -39,25 +44,23 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cespare/cp"
|
"github.com/cespare/cp"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/signify"
|
"github.com/ethereum/go-ethereum/crypto/signify"
|
||||||
"github.com/ethereum/go-ethereum/internal/build"
|
"github.com/ethereum/go-ethereum/internal/build"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -109,7 +112,7 @@ var (
|
||||||
// A debian package is created for all executables listed here.
|
// A debian package is created for all executables listed here.
|
||||||
debEthereum = debPackage{
|
debEthereum = debPackage{
|
||||||
Name: "ethereum",
|
Name: "ethereum",
|
||||||
Version: params.Version,
|
Version: version.Semantic,
|
||||||
Executables: debExecutables,
|
Executables: debExecutables,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,11 +123,12 @@ var (
|
||||||
|
|
||||||
// Distros for which packages are created
|
// Distros for which packages are created
|
||||||
debDistros = []string{
|
debDistros = []string{
|
||||||
"xenial", // 16.04, EOL: 04/2026
|
"xenial", // 16.04, EOL: 04/2026
|
||||||
"bionic", // 18.04, EOL: 04/2028
|
"bionic", // 18.04, EOL: 04/2028
|
||||||
"focal", // 20.04, EOL: 04/2030
|
"focal", // 20.04, EOL: 04/2030
|
||||||
"jammy", // 22.04, EOL: 04/2032
|
"jammy", // 22.04, EOL: 04/2032
|
||||||
"noble", // 24.04, EOL: 04/2034
|
"noble", // 24.04, EOL: 04/2034
|
||||||
|
"oracular", // 24.10, EOL: 07/2025
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is where the tests should be unpacked.
|
// This is where the tests should be unpacked.
|
||||||
|
|
@ -143,7 +147,7 @@ func executablePath(name string) string {
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(log.Lshortfile)
|
log.SetFlags(log.Lshortfile)
|
||||||
|
|
||||||
if !common.FileExist(filepath.Join("build", "ci.go")) {
|
if !build.FileExist(filepath.Join("build", "ci.go")) {
|
||||||
log.Fatal("this script must be run from the root of the repository")
|
log.Fatal("this script must be run from the root of the repository")
|
||||||
}
|
}
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
|
|
@ -156,6 +160,12 @@ func main() {
|
||||||
doTest(os.Args[2:])
|
doTest(os.Args[2:])
|
||||||
case "lint":
|
case "lint":
|
||||||
doLint(os.Args[2:])
|
doLint(os.Args[2:])
|
||||||
|
case "check_tidy":
|
||||||
|
doCheckTidy()
|
||||||
|
case "check_generate":
|
||||||
|
doCheckGenerate()
|
||||||
|
case "check_baddeps":
|
||||||
|
doCheckBadDeps()
|
||||||
case "archive":
|
case "archive":
|
||||||
doArchive(os.Args[2:])
|
doArchive(os.Args[2:])
|
||||||
case "dockerx":
|
case "dockerx":
|
||||||
|
|
@ -168,8 +178,6 @@ func main() {
|
||||||
doPurge(os.Args[2:])
|
doPurge(os.Args[2:])
|
||||||
case "sanitycheck":
|
case "sanitycheck":
|
||||||
doSanityCheck()
|
doSanityCheck()
|
||||||
case "generate":
|
|
||||||
doGenerate()
|
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown command ", os.Args[1])
|
log.Fatal("unknown command ", os.Args[1])
|
||||||
}
|
}
|
||||||
|
|
@ -204,12 +212,6 @@ func doInstall(cmdline []string) {
|
||||||
// Configure the build.
|
// Configure the build.
|
||||||
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
||||||
|
|
||||||
// arm64 CI builders are memory-constrained and can't handle concurrent builds,
|
|
||||||
// better disable it. This check isn't the best, it should probably
|
|
||||||
// check for something in env instead.
|
|
||||||
if env.CI && runtime.GOARCH == "arm64" {
|
|
||||||
gobuild.Args = append(gobuild.Args, "-p", "1")
|
|
||||||
}
|
|
||||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||||
gobuild.Args = append(gobuild.Args, "-trimpath")
|
gobuild.Args = append(gobuild.Args, "-trimpath")
|
||||||
|
|
||||||
|
|
@ -225,8 +227,7 @@ func doInstall(cmdline []string) {
|
||||||
|
|
||||||
// Do the build!
|
// Do the build!
|
||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
args := make([]string, len(gobuild.Args))
|
args := slices.Clone(gobuild.Args)
|
||||||
copy(args, gobuild.Args)
|
|
||||||
args = append(args, "-o", executablePath(path.Base(pkg)))
|
args = append(args, "-o", executablePath(path.Base(pkg)))
|
||||||
args = append(args, pkg)
|
args = append(args, pkg)
|
||||||
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env})
|
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env})
|
||||||
|
|
@ -354,128 +355,93 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
|
||||||
return filepath.Join(cachedir, base)
|
return filepath.Join(cachedir, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashAllSourceFiles iterates all files under the top-level project directory
|
// doCheckTidy assets that the Go modules files are tidied already.
|
||||||
// computing the hash of each file (excluding files within the tests
|
func doCheckTidy() {
|
||||||
// subrepo)
|
targets := []string{"go.mod", "go.sum"}
|
||||||
func hashAllSourceFiles() (map[string]common.Hash, error) {
|
|
||||||
res := make(map[string]common.Hash)
|
hashes, err := build.HashFiles(targets)
|
||||||
err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error {
|
|
||||||
if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
if !d.Type().IsRegular() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// open the file and hash it
|
|
||||||
f, err := os.OpenFile(path, os.O_RDONLY, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
hasher := sha256.New()
|
|
||||||
if _, err := io.Copy(hasher, f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
res[path] = common.Hash(hasher.Sum(nil))
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Fatalf("failed to hash go.mod/go.sum: %v", err)
|
||||||
}
|
}
|
||||||
return res, nil
|
build.MustRun(new(build.GoToolchain).Go("mod", "tidy"))
|
||||||
}
|
|
||||||
|
|
||||||
// hashSourceFiles iterates the provided set of filepaths (relative to the top-level geth project directory)
|
tidied, err := build.HashFiles(targets)
|
||||||
// computing the hash of each file.
|
|
||||||
func hashSourceFiles(files []string) (map[string]common.Hash, error) {
|
|
||||||
res := make(map[string]common.Hash)
|
|
||||||
for _, filePath := range files {
|
|
||||||
f, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
hasher := sha256.New()
|
|
||||||
if _, err := io.Copy(hasher, f); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
res[filePath] = common.Hash(hasher.Sum(nil))
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// compareHashedFilesets compares two maps (key is relative file path to top-level geth directory, value is its hash)
|
|
||||||
// and returns the list of file paths whose hashes differed.
|
|
||||||
func compareHashedFilesets(preHashes map[string]common.Hash, postHashes map[string]common.Hash) []string {
|
|
||||||
updates := []string{}
|
|
||||||
for path, postHash := range postHashes {
|
|
||||||
preHash, ok := preHashes[path]
|
|
||||||
if !ok || preHash != postHash {
|
|
||||||
updates = append(updates, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return updates
|
|
||||||
}
|
|
||||||
|
|
||||||
func doGoModTidy() {
|
|
||||||
targetFiles := []string{"go.mod", "go.sum"}
|
|
||||||
preHashes, err := hashSourceFiles(targetFiles)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("failed to hash go.mod/go.sum", "err", err)
|
log.Fatalf("failed to rehash go.mod/go.sum: %v", err)
|
||||||
}
|
}
|
||||||
tc := new(build.GoToolchain)
|
if updates := build.DiffHashes(hashes, tidied); len(updates) > 0 {
|
||||||
c := tc.Go("mod", "tidy")
|
log.Fatalf("files changed on running 'go mod tidy': %v", updates)
|
||||||
build.MustRun(c)
|
|
||||||
postHashes, err := hashSourceFiles(targetFiles)
|
|
||||||
updates := compareHashedFilesets(preHashes, postHashes)
|
|
||||||
for _, updatedFile := range updates {
|
|
||||||
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
|
||||||
}
|
|
||||||
if len(updates) != 0 {
|
|
||||||
log.Fatal("go.sum and/or go.mod were updated by running 'go mod tidy'")
|
|
||||||
}
|
}
|
||||||
|
fmt.Println("No untidy module files detected.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// doGenerate ensures that re-generating generated files does not cause
|
// doCheckGenerate ensures that re-generating generated files does not cause
|
||||||
// any mutations in the source file tree: i.e. all generated files were
|
// any mutations in the source file tree.
|
||||||
// updated and committed. Any stale generated files are updated.
|
func doCheckGenerate() {
|
||||||
func doGenerate() {
|
|
||||||
var (
|
var (
|
||||||
tc = new(build.GoToolchain)
|
|
||||||
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
|
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
|
||||||
verify = flag.Bool("verify", false, "check whether any files are changed by go generate")
|
|
||||||
)
|
)
|
||||||
|
// Compute the origin hashes of all the files
|
||||||
|
var hashes map[string][32]byte
|
||||||
|
|
||||||
protocPath := downloadProtoc(*cachedir)
|
var err error
|
||||||
protocGenGoPath := downloadProtocGenGo(*cachedir)
|
hashes, err = build.HashFolder(".", []string{"tests/testdata", "build/cache"})
|
||||||
|
if err != nil {
|
||||||
var preHashes map[string]common.Hash
|
log.Fatal("Error computing hashes", "err", err)
|
||||||
if *verify {
|
|
||||||
var err error
|
|
||||||
preHashes, err = hashAllSourceFiles()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("failed to compute map of source hashes", "err", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Run any go generate steps we might be missing
|
||||||
c := tc.Go("generate", "./...")
|
var (
|
||||||
|
protocPath = downloadProtoc(*cachedir)
|
||||||
|
protocGenGoPath = downloadProtocGenGo(*cachedir)
|
||||||
|
)
|
||||||
|
c := new(build.GoToolchain).Go("generate", "./...")
|
||||||
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
||||||
c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
|
c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
|
||||||
build.MustRun(c)
|
build.MustRun(c)
|
||||||
|
|
||||||
if !*verify {
|
// Check if generate file hashes have changed
|
||||||
return
|
generated, err := build.HashFolder(".", []string{"tests/testdata", "build/cache"})
|
||||||
}
|
|
||||||
// Check if files were changed.
|
|
||||||
postHashes, err := hashAllSourceFiles()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error computing source tree file hashes", "err", err)
|
log.Fatalf("Error re-computing hashes: %v", err)
|
||||||
}
|
}
|
||||||
updates := compareHashedFilesets(preHashes, postHashes)
|
updates := build.DiffHashes(hashes, generated)
|
||||||
for _, updatedFile := range updates {
|
for _, file := range updates {
|
||||||
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
log.Printf("File changed: %s", file)
|
||||||
}
|
}
|
||||||
if len(updates) != 0 {
|
if len(updates) != 0 {
|
||||||
log.Fatal("One or more generated files were updated by running 'go generate ./...'")
|
log.Fatal("One or more generated files were updated by running 'go generate ./...'")
|
||||||
}
|
}
|
||||||
|
fmt.Println("No stale files detected.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// doCheckBadDeps verifies whether certain unintended dependencies between some
|
||||||
|
// packages leak into the codebase due to a refactor. This is not an exhaustive
|
||||||
|
// list, rather something we build up over time at sensitive places.
|
||||||
|
func doCheckBadDeps() {
|
||||||
|
baddeps := [][2]string{
|
||||||
|
// Rawdb tends to be a dumping ground for db utils, sometimes leaking the db itself
|
||||||
|
{"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/leveldb"},
|
||||||
|
{"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/pebbledb"},
|
||||||
|
}
|
||||||
|
tc := new(build.GoToolchain)
|
||||||
|
|
||||||
|
var failed bool
|
||||||
|
for _, rule := range baddeps {
|
||||||
|
out, err := tc.Go("list", "-deps", rule[0]).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to list '%s' dependencies: %v", rule[0], err)
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(string(out), "\n") {
|
||||||
|
if strings.TrimSpace(line) == rule[1] {
|
||||||
|
log.Printf("Found bad dependency '%s' -> '%s'", rule[0], rule[1])
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if failed {
|
||||||
|
log.Fatalf("Bad dependencies detected.")
|
||||||
|
}
|
||||||
|
fmt.Println("No bad dependencies detected.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// doLint runs golangci-lint on requested packages.
|
// doLint runs golangci-lint on requested packages.
|
||||||
|
|
@ -492,8 +458,6 @@ func doLint(cmdline []string) {
|
||||||
linter := downloadLinter(*cachedir)
|
linter := downloadLinter(*cachedir)
|
||||||
lflags := []string{"run", "--config", ".golangci.yml"}
|
lflags := []string{"run", "--config", ".golangci.yml"}
|
||||||
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
||||||
|
|
||||||
doGoModTidy()
|
|
||||||
fmt.Println("You have achieved perfection.")
|
fmt.Println("You have achieved perfection.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -637,7 +601,7 @@ func doArchive(cmdline []string) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
env = build.Env()
|
env = build.Env()
|
||||||
basegeth = archiveBasename(*arch, params.ArchiveVersion(env.Commit))
|
basegeth = archiveBasename(*arch, version.Archive(env.Commit))
|
||||||
geth = "geth-" + basegeth + ext
|
geth = "geth-" + basegeth + ext
|
||||||
alltools = "geth-alltools-" + basegeth + ext
|
alltools = "geth-alltools-" + basegeth + ext
|
||||||
)
|
)
|
||||||
|
|
@ -757,7 +721,7 @@ func doDockerBuildx(cmdline []string) {
|
||||||
case env.Branch == "master":
|
case env.Branch == "master":
|
||||||
tags = []string{"latest"}
|
tags = []string{"latest"}
|
||||||
case strings.HasPrefix(env.Tag, "v1."):
|
case strings.HasPrefix(env.Tag, "v1."):
|
||||||
tags = []string{"stable", fmt.Sprintf("release-1.%d", params.VersionMinor), "v" + params.Version}
|
tags = []string{"stable", fmt.Sprintf("release-%v", version.Family), "v" + version.Semantic}
|
||||||
}
|
}
|
||||||
// Need to create a mult-arch builder
|
// Need to create a mult-arch builder
|
||||||
build.MustRunCommand("docker", "buildx", "create", "--use", "--name", "multi-arch-builder", "--platform", *platform)
|
build.MustRunCommand("docker", "buildx", "create", "--use", "--name", "multi-arch-builder", "--platform", *platform)
|
||||||
|
|
@ -773,7 +737,7 @@ func doDockerBuildx(cmdline []string) {
|
||||||
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
||||||
build.MustRunCommand("docker", "buildx", "build",
|
build.MustRunCommand("docker", "buildx", "build",
|
||||||
"--build-arg", "COMMIT="+env.Commit,
|
"--build-arg", "COMMIT="+env.Commit,
|
||||||
"--build-arg", "VERSION="+params.VersionWithMeta,
|
"--build-arg", "VERSION="+version.WithMeta,
|
||||||
"--build-arg", "BUILDNUM="+env.Buildnum,
|
"--build-arg", "BUILDNUM="+env.Buildnum,
|
||||||
"--tag", gethImage,
|
"--tag", gethImage,
|
||||||
"--platform", *platform,
|
"--platform", *platform,
|
||||||
|
|
@ -927,15 +891,21 @@ func ppaUpload(workdir, ppa, sshUser string, files []string) {
|
||||||
var idfile string
|
var idfile string
|
||||||
if sshkey := getenvBase64("PPA_SSH_KEY"); len(sshkey) > 0 {
|
if sshkey := getenvBase64("PPA_SSH_KEY"); len(sshkey) > 0 {
|
||||||
idfile = filepath.Join(workdir, "sshkey")
|
idfile = filepath.Join(workdir, "sshkey")
|
||||||
if !common.FileExist(idfile) {
|
if !build.FileExist(idfile) {
|
||||||
os.WriteFile(idfile, sshkey, 0600)
|
os.WriteFile(idfile, sshkey, 0600)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Upload
|
// Upload. This doesn't always work, so try up to three times.
|
||||||
dest := sshUser + "@ppa.launchpad.net"
|
dest := sshUser + "@ppa.launchpad.net"
|
||||||
if err := build.UploadSFTP(idfile, dest, incomingDir, files); err != nil {
|
for i := 0; i < 3; i++ {
|
||||||
log.Fatal(err)
|
err := build.UploadSFTP(idfile, dest, incomingDir, files)
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("PPA upload failed:", err)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
}
|
}
|
||||||
|
log.Fatal("PPA upload failed all attempts.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getenvBase64(variable string) []byte {
|
func getenvBase64(variable string) []byte {
|
||||||
|
|
@ -1152,19 +1122,19 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
// Build the installer. This assumes that all the needed files have been previously
|
// Build the installer. This assumes that all the needed files have been previously
|
||||||
// built (don't mix building and packaging to keep cross compilation complexity to a
|
// built (don't mix building and packaging to keep cross compilation complexity to a
|
||||||
// minimum).
|
// minimum).
|
||||||
version := strings.Split(params.Version, ".")
|
ver := strings.Split(version.Semantic, ".")
|
||||||
if env.Commit != "" {
|
if env.Commit != "" {
|
||||||
version[2] += "-" + env.Commit[:8]
|
ver[2] += "-" + env.Commit[:8]
|
||||||
}
|
}
|
||||||
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe")
|
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, version.Archive(env.Commit)) + ".exe")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to convert installer file path: %v", err)
|
log.Fatalf("Failed to convert installer file path: %v", err)
|
||||||
}
|
}
|
||||||
build.MustRunCommand("makensis.exe",
|
build.MustRunCommand("makensis.exe",
|
||||||
"/DOUTPUTFILE="+installer,
|
"/DOUTPUTFILE="+installer,
|
||||||
"/DMAJORVERSION="+version[0],
|
"/DMAJORVERSION="+ver[0],
|
||||||
"/DMINORVERSION="+version[1],
|
"/DMINORVERSION="+ver[1],
|
||||||
"/DBUILDVERSION="+version[2],
|
"/DBUILDVERSION="+ver[2],
|
||||||
"/DARCH="+*arch,
|
"/DARCH="+*arch,
|
||||||
filepath.Join(*workdir, "geth.nsi"),
|
filepath.Join(*workdir, "geth.nsi"),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/blsync"
|
"github.com/ethereum/go-ethereum/beacon/blsync"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
|
@ -33,7 +34,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := flags.NewApp("beacon light syncer tool")
|
app := flags.NewApp("beacon light syncer tool")
|
||||||
app.Flags = flags.Merge([]cli.Flag{
|
app.Flags = slices.Concat([]cli.Flag{
|
||||||
utils.BeaconApiFlag,
|
utils.BeaconApiFlag,
|
||||||
utils.BeaconApiHeaderFlag,
|
utils.BeaconApiHeaderFlag,
|
||||||
utils.BeaconThresholdFlag,
|
utils.BeaconThresholdFlag,
|
||||||
|
|
@ -45,6 +46,7 @@ func main() {
|
||||||
//TODO datadir for optional permanent database
|
//TODO datadir for optional permanent database
|
||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.SepoliaFlag,
|
utils.SepoliaFlag,
|
||||||
|
utils.HoleskyFlag,
|
||||||
utils.BlsyncApiFlag,
|
utils.BlsyncApiFlag,
|
||||||
utils.BlsyncJWTSecretFlag,
|
utils.BlsyncJWTSecretFlag,
|
||||||
},
|
},
|
||||||
|
|
@ -68,7 +70,7 @@ func main() {
|
||||||
|
|
||||||
func sync(ctx *cli.Context) error {
|
func sync(ctx *cli.Context) error {
|
||||||
// set up blsync
|
// set up blsync
|
||||||
client := blsync.NewClient(ctx)
|
client := blsync.NewClient(utils.MakeBeaconLightConfig(ctx))
|
||||||
client.SetEngineRPC(makeRPCClient(ctx))
|
client.SetEngineRPC(makeRPCClient(ctx))
|
||||||
client.Start()
|
client.Start()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -30,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
|
@ -84,7 +84,7 @@ var (
|
||||||
Name: "listen",
|
Name: "listen",
|
||||||
Usage: "Runs a discovery node",
|
Usage: "Runs a discovery node",
|
||||||
Action: discv4Listen,
|
Action: discv4Listen,
|
||||||
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{
|
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{
|
||||||
httpAddrFlag,
|
httpAddrFlag,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ var (
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv4Crawl,
|
Action: discv4Crawl,
|
||||||
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}),
|
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}),
|
||||||
}
|
}
|
||||||
discv4TestCommand = &cli.Command{
|
discv4TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ var (
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv5Crawl,
|
Action: discv5Crawl,
|
||||||
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{
|
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{
|
||||||
crawlTimeoutFlag,
|
crawlTimeoutFlag,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ func (c *Chain) AccountsInHashOrder() []state.DumpAccount {
|
||||||
list := make([]state.DumpAccount, len(c.state))
|
list := make([]state.DumpAccount, len(c.state))
|
||||||
i := 0
|
i := 0
|
||||||
for addr, acc := range c.state {
|
for addr, acc := range c.state {
|
||||||
addr := addr
|
|
||||||
list[i] = acc
|
list[i] = acc
|
||||||
list[i].Address = &addr
|
list[i].Address = &addr
|
||||||
if len(acc.AddressHash) != 32 {
|
if len(acc.AddressHash) != 32 {
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,6 @@ a key before startingHash (wrong order). The server should return the first avai
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
tc := tc
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +430,6 @@ of the test account. The server should return slots [2,3] (i.e. the 'next availa
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
tc := tc
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
|
|
@ -528,7 +526,6 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
tc := tc
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
|
|
@ -734,7 +731,6 @@ The server should reject the request.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
tc := tc
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
"shanghaiTime": 780,
|
"shanghaiTime": 780,
|
||||||
"cancunTime": 840,
|
"cancunTime": 840,
|
||||||
"terminalTotalDifficulty": 9454784,
|
"terminalTotalDifficulty": 9454784,
|
||||||
"terminalTotalDifficultyPassed": true,
|
|
||||||
"ethash": {}
|
"ethash": {}
|
||||||
},
|
},
|
||||||
"nonce": "0x0",
|
"nonce": "0x0",
|
||||||
|
|
|
||||||
200
cmd/evm/eofparse.go
Normal file
200
cmd/evm/eofparse.go
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
// 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"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
jt = vm.NewPragueEOFInstructionSetForTesting()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
jt vm.JumpTable
|
||||||
|
initcode = "INITCODE"
|
||||||
|
)
|
||||||
|
|
||||||
|
func eofParseAction(ctx *cli.Context) error {
|
||||||
|
// If `--test` is set, parse and validate the reference test at the provided path.
|
||||||
|
if ctx.IsSet(refTestFlag.Name) {
|
||||||
|
var (
|
||||||
|
file = ctx.String(refTestFlag.Name)
|
||||||
|
executedTests int
|
||||||
|
passedTests int
|
||||||
|
)
|
||||||
|
err := filepath.Walk(file, func(path string, info fs.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Debug("Executing test", "name", info.Name())
|
||||||
|
passed, tot, err := executeTest(path)
|
||||||
|
passedTests += passed
|
||||||
|
executedTests += tot
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("Executed tests", "passed", passedTests, "total executed", executedTests)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// If `--hex` is set, parse and validate the hex string argument.
|
||||||
|
if ctx.IsSet(hexFlag.Name) {
|
||||||
|
if _, err := parseAndValidate(ctx.String(hexFlag.Name), false); err != nil {
|
||||||
|
return fmt.Errorf("err: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Println("OK")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// If neither are passed in, read input from stdin.
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
|
||||||
|
for scanner.Scan() {
|
||||||
|
l := strings.TrimSpace(scanner.Text())
|
||||||
|
if strings.HasPrefix(l, "#") || l == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := parseAndValidate(l, false); err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type refTests struct {
|
||||||
|
Vectors map[string]eOFTest `json:"vectors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type eOFTest struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Results map[string]etResult `json:"results"`
|
||||||
|
ContainerKind string `json:"containerKind"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type etResult struct {
|
||||||
|
Result bool `json:"result"`
|
||||||
|
Exception string `json:"exception,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeTest(path string) (int, int, error) {
|
||||||
|
src, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
var testsByName map[string]refTests
|
||||||
|
if err := json.Unmarshal(src, &testsByName); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
passed, total := 0, 0
|
||||||
|
for testsName, tests := range testsByName {
|
||||||
|
for name, tt := range tests.Vectors {
|
||||||
|
for fork, r := range tt.Results {
|
||||||
|
total++
|
||||||
|
_, err := parseAndValidate(tt.Code, tt.ContainerKind == initcode)
|
||||||
|
if r.Result && err != nil {
|
||||||
|
log.Error("Test failure, expected validation success", "name", testsName, "idx", name, "fork", fork, "err", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !r.Result && err == nil {
|
||||||
|
log.Error("Test failure, expected validation error", "name", testsName, "idx", name, "fork", fork, "have err", r.Exception, "err", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
passed++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passed, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAndValidate(s string, isInitCode bool) (*vm.Container, error) {
|
||||||
|
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to decode data: %w", err)
|
||||||
|
}
|
||||||
|
return parse(b, isInitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(b []byte, isInitCode bool) (*vm.Container, error) {
|
||||||
|
var c vm.Container
|
||||||
|
if err := c.UnmarshalBinary(b, isInitCode); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.ValidateCode(&jt, isInitCode); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func eofDumpAction(ctx *cli.Context) error {
|
||||||
|
// If `--hex` is set, parse and validate the hex string argument.
|
||||||
|
if ctx.IsSet(hexFlag.Name) {
|
||||||
|
return eofDump(ctx.String(hexFlag.Name))
|
||||||
|
}
|
||||||
|
// Otherwise read from stdin
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
|
||||||
|
for scanner.Scan() {
|
||||||
|
l := strings.TrimSpace(scanner.Text())
|
||||||
|
if strings.HasPrefix(l, "#") || l == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := eofDump(l); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
return scanner.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func eofDump(hexdata string) error {
|
||||||
|
if len(hexdata) >= 2 && strings.HasPrefix(hexdata, "0x") {
|
||||||
|
hexdata = hexdata[2:]
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(hexdata)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to decode data: %w", err)
|
||||||
|
}
|
||||||
|
var c vm.Container
|
||||||
|
if err := c.UnmarshalBinary(b, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(c.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
166
cmd/evm/eofparse_test.go
Normal file
166
cmd/evm/eofparse_test.go
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FuzzEofParsing(f *testing.F) {
|
||||||
|
// Seed with corpus from execution-spec-tests
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i)
|
||||||
|
corpus, err := os.Open(fname)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
f.Logf("Reading seed data from %v", fname)
|
||||||
|
scanner := bufio.NewScanner(corpus)
|
||||||
|
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
||||||
|
for scanner.Scan() {
|
||||||
|
s := scanner.Text()
|
||||||
|
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // rotten corpus
|
||||||
|
}
|
||||||
|
f.Add(b)
|
||||||
|
}
|
||||||
|
corpus.Close()
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
panic(err) // rotten corpus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// And do the fuzzing
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
var (
|
||||||
|
jt = vm.NewPragueEOFInstructionSetForTesting()
|
||||||
|
c vm.Container
|
||||||
|
)
|
||||||
|
cpy := common.CopyBytes(data)
|
||||||
|
if err := c.UnmarshalBinary(data, true); err == nil {
|
||||||
|
c.ValidateCode(&jt, true)
|
||||||
|
if have := c.MarshalBinary(); !bytes.Equal(have, data) {
|
||||||
|
t.Fatal("Unmarshal-> Marshal failure!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := c.UnmarshalBinary(data, false); err == nil {
|
||||||
|
c.ValidateCode(&jt, false)
|
||||||
|
if have := c.MarshalBinary(); !bytes.Equal(have, data) {
|
||||||
|
t.Fatal("Unmarshal-> Marshal failure!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !bytes.Equal(cpy, data) {
|
||||||
|
panic("data modified during unmarshalling")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEofParseInitcode(t *testing.T) {
|
||||||
|
testEofParse(t, true, "testdata/eof/results.initcode.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEofParseRegular(t *testing.T) {
|
||||||
|
testEofParse(t, false, "testdata/eof/results.regular.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEofParse(t *testing.T, isInitCode bool, wantFile string) {
|
||||||
|
var wantFn func() string
|
||||||
|
var wantLoc = 0
|
||||||
|
{ // Configure the want-reader
|
||||||
|
wants, err := os.Open(wantFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(wants)
|
||||||
|
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
||||||
|
wantFn = func() string {
|
||||||
|
if scanner.Scan() {
|
||||||
|
wantLoc++
|
||||||
|
return scanner.Text()
|
||||||
|
}
|
||||||
|
return "end of file reached"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i)
|
||||||
|
corpus, err := os.Open(fname)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t.Logf("# Reading seed data from %v", fname)
|
||||||
|
scanner := bufio.NewScanner(corpus)
|
||||||
|
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
||||||
|
line := 1
|
||||||
|
for scanner.Scan() {
|
||||||
|
s := scanner.Text()
|
||||||
|
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // rotten corpus
|
||||||
|
}
|
||||||
|
have := "OK"
|
||||||
|
if _, err := parse(b, isInitCode); err != nil {
|
||||||
|
have = fmt.Sprintf("ERR: %v", err)
|
||||||
|
}
|
||||||
|
if false { // Change this to generate the want-output
|
||||||
|
fmt.Printf("%v\n", have)
|
||||||
|
} else {
|
||||||
|
want := wantFn()
|
||||||
|
if have != want {
|
||||||
|
if len(want) > 100 {
|
||||||
|
want = want[:100]
|
||||||
|
}
|
||||||
|
if len(b) > 100 {
|
||||||
|
b = b[:100]
|
||||||
|
}
|
||||||
|
t.Errorf("%v:%d\n%v\ninput %x\nisInit: %v\nhave: %q\nwant: %q\n",
|
||||||
|
fname, line, fmt.Sprintf("%v:%d", wantFile, wantLoc), b, isInitCode, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line++
|
||||||
|
}
|
||||||
|
corpus.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEofParse(b *testing.B) {
|
||||||
|
corpus, err := os.Open("testdata/eof/eof_benches.txt")
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer corpus.Close()
|
||||||
|
scanner := bufio.NewScanner(corpus)
|
||||||
|
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
||||||
|
line := 1
|
||||||
|
for scanner.Scan() {
|
||||||
|
s := scanner.Text()
|
||||||
|
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
data, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err) // rotten corpus
|
||||||
|
}
|
||||||
|
b.Run(fmt.Sprintf("test-%d", line), func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.SetBytes(int64(len(data)))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = parse(data, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
line++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"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/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
|
|
@ -50,6 +51,8 @@ type Prestate struct {
|
||||||
Pre types.GenesisAlloc `json:"pre"`
|
Pre types.GenesisAlloc `json:"pre"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:generate go run github.com/fjl/gencodec -type ExecutionResult -field-override executionResultMarshaling -out gen_execresult.go
|
||||||
|
|
||||||
// ExecutionResult contains the execution status after running a state test, any
|
// ExecutionResult contains the execution status after running a state test, any
|
||||||
// error that might have occurred and a dump of the final state if requested.
|
// error that might have occurred and a dump of the final state if requested.
|
||||||
type ExecutionResult struct {
|
type ExecutionResult struct {
|
||||||
|
|
@ -66,8 +69,12 @@ type ExecutionResult struct {
|
||||||
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:"blobGasUsed,omitempty"`
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
|
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
||||||
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
|
Requests [][]byte `json:"requests,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type executionResultMarshaling struct {
|
||||||
|
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
|
|
@ -125,7 +132,7 @@ 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,
|
||||||
txIt txIterator, miningReward int64,
|
txIt txIterator, miningReward int64,
|
||||||
getTracerFn func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error)) (*state.StateDB, *ExecutionResult, []byte, error) {
|
getTracerFn func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, 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
|
||||||
|
|
@ -241,7 +248,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracer, traceOutput, err := getTracerFn(txIndex, tx.Hash())
|
tracer, traceOutput, err := getTracerFn(txIndex, tx.Hash(), chainConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -367,6 +374,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
|
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
|
||||||
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
|
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gather the execution-layer triggered requests.
|
||||||
|
var requests [][]byte
|
||||||
|
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
||||||
|
// EIP-6110 deposits
|
||||||
|
var allLogs []*types.Log
|
||||||
|
for _, receipt := range receipts {
|
||||||
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
|
}
|
||||||
|
depositRequests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
||||||
|
}
|
||||||
|
requests = append(requests, depositRequests)
|
||||||
|
// create EVM for system calls
|
||||||
|
vmenv := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
||||||
|
// EIP-7002 withdrawals
|
||||||
|
requests = append(requests, core.ProcessWithdrawalQueue(vmenv, statedb))
|
||||||
|
// EIP-7251 consolidations
|
||||||
|
requests = append(requests, core.ProcessConsolidationQueue(vmenv, statedb))
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
|
|
@ -394,28 +423,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
if chainConfig.IsPrague(vmContext.BlockNumber) && chainConfig.Bor == nil {
|
if requests != nil {
|
||||||
// Parse the requests from the logs
|
// Set requestsHash on block.
|
||||||
var allLogs []*types.Log
|
h := types.CalcRequestsHash(requests)
|
||||||
for _, receipt := range receipts {
|
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
|
||||||
}
|
|
||||||
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
|
||||||
}
|
|
||||||
// Calculate the requests root
|
|
||||||
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
|
||||||
execRs.RequestsHash = &h
|
execRs.RequestsHash = &h
|
||||||
// Get the deposits from the requests
|
for i := range requests {
|
||||||
deposits := make(types.Deposits, 0)
|
// remove prefix
|
||||||
for _, req := range requests {
|
requests[i] = requests[i][1:]
|
||||||
if dep, ok := req.Inner().(*types.Deposit); ok {
|
|
||||||
deposits = append(deposits, dep)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
execRs.DepositRequests = &deposits
|
execRs.Requests = requests
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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())
|
statedb, err = state.New(root, statedb.Database())
|
||||||
|
|
|
||||||
134
cmd/evm/internal/t8ntool/gen_execresult.go
Normal file
134
cmd/evm/internal/t8ntool/gen_execresult.go
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package t8ntool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*executionResultMarshaling)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals as JSON.
|
||||||
|
func (e ExecutionResult) MarshalJSON() ([]byte, error) {
|
||||||
|
type ExecutionResult struct {
|
||||||
|
StateRoot common.Hash `json:"stateRoot"`
|
||||||
|
TxRoot common.Hash `json:"txRoot"`
|
||||||
|
ReceiptRoot common.Hash `json:"receiptsRoot"`
|
||||||
|
LogsHash common.Hash `json:"logsHash"`
|
||||||
|
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
|
Receipts types.Receipts `json:"receipts"`
|
||||||
|
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
||||||
|
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
||||||
|
}
|
||||||
|
var enc ExecutionResult
|
||||||
|
enc.StateRoot = e.StateRoot
|
||||||
|
enc.TxRoot = e.TxRoot
|
||||||
|
enc.ReceiptRoot = e.ReceiptRoot
|
||||||
|
enc.LogsHash = e.LogsHash
|
||||||
|
enc.Bloom = e.Bloom
|
||||||
|
enc.Receipts = e.Receipts
|
||||||
|
enc.Rejected = e.Rejected
|
||||||
|
enc.Difficulty = e.Difficulty
|
||||||
|
enc.GasUsed = e.GasUsed
|
||||||
|
enc.BaseFee = e.BaseFee
|
||||||
|
enc.WithdrawalsRoot = e.WithdrawalsRoot
|
||||||
|
enc.CurrentExcessBlobGas = e.CurrentExcessBlobGas
|
||||||
|
enc.CurrentBlobGasUsed = e.CurrentBlobGasUsed
|
||||||
|
enc.RequestsHash = e.RequestsHash
|
||||||
|
if e.Requests != nil {
|
||||||
|
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
|
||||||
|
for k, v := range e.Requests {
|
||||||
|
enc.Requests[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
|
func (e *ExecutionResult) UnmarshalJSON(input []byte) error {
|
||||||
|
type ExecutionResult struct {
|
||||||
|
StateRoot *common.Hash `json:"stateRoot"`
|
||||||
|
TxRoot *common.Hash `json:"txRoot"`
|
||||||
|
ReceiptRoot *common.Hash `json:"receiptsRoot"`
|
||||||
|
LogsHash *common.Hash `json:"logsHash"`
|
||||||
|
Bloom *types.Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
|
Receipts *types.Receipts `json:"receipts"`
|
||||||
|
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
||||||
|
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
||||||
|
}
|
||||||
|
var dec ExecutionResult
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.StateRoot != nil {
|
||||||
|
e.StateRoot = *dec.StateRoot
|
||||||
|
}
|
||||||
|
if dec.TxRoot != nil {
|
||||||
|
e.TxRoot = *dec.TxRoot
|
||||||
|
}
|
||||||
|
if dec.ReceiptRoot != nil {
|
||||||
|
e.ReceiptRoot = *dec.ReceiptRoot
|
||||||
|
}
|
||||||
|
if dec.LogsHash != nil {
|
||||||
|
e.LogsHash = *dec.LogsHash
|
||||||
|
}
|
||||||
|
if dec.Bloom == nil {
|
||||||
|
return errors.New("missing required field 'logsBloom' for ExecutionResult")
|
||||||
|
}
|
||||||
|
e.Bloom = *dec.Bloom
|
||||||
|
if dec.Receipts != nil {
|
||||||
|
e.Receipts = *dec.Receipts
|
||||||
|
}
|
||||||
|
if dec.Rejected != nil {
|
||||||
|
e.Rejected = dec.Rejected
|
||||||
|
}
|
||||||
|
if dec.Difficulty == nil {
|
||||||
|
return errors.New("missing required field 'currentDifficulty' for ExecutionResult")
|
||||||
|
}
|
||||||
|
e.Difficulty = dec.Difficulty
|
||||||
|
if dec.GasUsed != nil {
|
||||||
|
e.GasUsed = *dec.GasUsed
|
||||||
|
}
|
||||||
|
if dec.BaseFee != nil {
|
||||||
|
e.BaseFee = dec.BaseFee
|
||||||
|
}
|
||||||
|
if dec.WithdrawalsRoot != nil {
|
||||||
|
e.WithdrawalsRoot = dec.WithdrawalsRoot
|
||||||
|
}
|
||||||
|
if dec.CurrentExcessBlobGas != nil {
|
||||||
|
e.CurrentExcessBlobGas = dec.CurrentExcessBlobGas
|
||||||
|
}
|
||||||
|
if dec.CurrentBlobGasUsed != nil {
|
||||||
|
e.CurrentBlobGasUsed = dec.CurrentBlobGasUsed
|
||||||
|
}
|
||||||
|
if dec.RequestsHash != nil {
|
||||||
|
e.RequestsHash = dec.RequestsHash
|
||||||
|
}
|
||||||
|
if dec.Requests != nil {
|
||||||
|
e.Requests = make([][]byte, len(dec.Requests))
|
||||||
|
for k, v := range dec.Requests {
|
||||||
|
e.Requests[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -84,7 +84,9 @@ type input struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Transition(ctx *cli.Context) error {
|
func Transition(ctx *cli.Context) error {
|
||||||
var getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) { return nil, nil, nil }
|
var getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
baseDir, err := createBasedir(ctx)
|
baseDir, err := createBasedir(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -99,7 +101,7 @@ func Transition(ctx *cli.Context) error {
|
||||||
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
getTracer = func(txIndex int, txHash common.Hash, _ *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
|
|
@ -123,12 +125,12 @@ func Transition(ctx *cli.Context) error {
|
||||||
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
||||||
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
}
|
}
|
||||||
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config)
|
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config, chainConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
136
cmd/evm/main.go
136
cmd/evm/main.go
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
|
@ -139,61 +140,90 @@ var (
|
||||||
Usage: "enable return data output",
|
Usage: "enable return data output",
|
||||||
Category: flags.VMCategory,
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
|
refTestFlag = &cli.StringFlag{
|
||||||
|
Name: "test",
|
||||||
|
Usage: "Path to EOF validation reference test.",
|
||||||
|
}
|
||||||
|
hexFlag = &cli.StringFlag{
|
||||||
|
Name: "hex",
|
||||||
|
Usage: "single container data parse and validation",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var stateTransitionCommand = &cli.Command{
|
var (
|
||||||
Name: "transition",
|
stateTransitionCommand = &cli.Command{
|
||||||
Aliases: []string{"t8n"},
|
Name: "transition",
|
||||||
Usage: "Executes a full state transition",
|
Aliases: []string{"t8n"},
|
||||||
Action: t8ntool.Transition,
|
Usage: "Executes a full state transition",
|
||||||
Flags: []cli.Flag{
|
Action: t8ntool.Transition,
|
||||||
t8ntool.TraceFlag,
|
Flags: []cli.Flag{
|
||||||
t8ntool.TraceTracerFlag,
|
t8ntool.TraceFlag,
|
||||||
t8ntool.TraceTracerConfigFlag,
|
t8ntool.TraceTracerFlag,
|
||||||
t8ntool.TraceEnableMemoryFlag,
|
t8ntool.TraceTracerConfigFlag,
|
||||||
t8ntool.TraceDisableStackFlag,
|
t8ntool.TraceEnableMemoryFlag,
|
||||||
t8ntool.TraceEnableReturnDataFlag,
|
t8ntool.TraceDisableStackFlag,
|
||||||
t8ntool.TraceEnableCallFramesFlag,
|
t8ntool.TraceEnableReturnDataFlag,
|
||||||
t8ntool.OutputBasedir,
|
t8ntool.TraceEnableCallFramesFlag,
|
||||||
t8ntool.OutputAllocFlag,
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputResultFlag,
|
t8ntool.OutputAllocFlag,
|
||||||
t8ntool.OutputBodyFlag,
|
t8ntool.OutputResultFlag,
|
||||||
t8ntool.InputAllocFlag,
|
t8ntool.OutputBodyFlag,
|
||||||
t8ntool.InputEnvFlag,
|
t8ntool.InputAllocFlag,
|
||||||
t8ntool.InputTxsFlag,
|
t8ntool.InputEnvFlag,
|
||||||
t8ntool.ForknameFlag,
|
t8ntool.InputTxsFlag,
|
||||||
t8ntool.ChainIDFlag,
|
t8ntool.ForknameFlag,
|
||||||
t8ntool.RewardFlag,
|
t8ntool.ChainIDFlag,
|
||||||
},
|
t8ntool.RewardFlag,
|
||||||
}
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var transactionCommand = &cli.Command{
|
transactionCommand = &cli.Command{
|
||||||
Name: "transaction",
|
Name: "transaction",
|
||||||
Aliases: []string{"t9n"},
|
Aliases: []string{"t9n"},
|
||||||
Usage: "Performs transaction validation",
|
Usage: "Performs transaction validation",
|
||||||
Action: t8ntool.Transaction,
|
Action: t8ntool.Transaction,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
t8ntool.InputTxsFlag,
|
t8ntool.InputTxsFlag,
|
||||||
t8ntool.ChainIDFlag,
|
t8ntool.ChainIDFlag,
|
||||||
t8ntool.ForknameFlag,
|
t8ntool.ForknameFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var blockBuilderCommand = &cli.Command{
|
blockBuilderCommand = &cli.Command{
|
||||||
Name: "block-builder",
|
Name: "block-builder",
|
||||||
Aliases: []string{"b11r"},
|
Aliases: []string{"b11r"},
|
||||||
Usage: "Builds a block",
|
Usage: "Builds a block",
|
||||||
Action: t8ntool.BuildBlock,
|
Action: t8ntool.BuildBlock,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
t8ntool.OutputBasedir,
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputBlockFlag,
|
t8ntool.OutputBlockFlag,
|
||||||
t8ntool.InputHeaderFlag,
|
t8ntool.InputHeaderFlag,
|
||||||
t8ntool.InputOmmersFlag,
|
t8ntool.InputOmmersFlag,
|
||||||
t8ntool.InputWithdrawalsFlag,
|
t8ntool.InputWithdrawalsFlag,
|
||||||
t8ntool.InputTxsRlpFlag,
|
t8ntool.InputTxsRlpFlag,
|
||||||
t8ntool.SealCliqueFlag,
|
t8ntool.SealCliqueFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
eofParseCommand = &cli.Command{
|
||||||
|
Name: "eofparse",
|
||||||
|
Aliases: []string{"eof"},
|
||||||
|
Usage: "Parses hex eof container and returns validation errors (if any)",
|
||||||
|
Action: eofParseAction,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
hexFlag,
|
||||||
|
refTestFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
eofDumpCommand = &cli.Command{
|
||||||
|
Name: "eofdump",
|
||||||
|
Usage: "Parses hex eof container and prints out human-readable representation of the container.",
|
||||||
|
Action: eofDumpAction,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
hexFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// vmFlags contains flags related to running the EVM.
|
// vmFlags contains flags related to running the EVM.
|
||||||
var vmFlags = []cli.Flag{
|
var vmFlags = []cli.Flag{
|
||||||
|
|
@ -226,7 +256,7 @@ var traceFlags = []cli.Flag{
|
||||||
var app = flags.NewApp("the evm command line interface")
|
var app = flags.NewApp("the evm command line interface")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags)
|
app.Flags = slices.Concat(vmFlags, traceFlags, debug.Flags)
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
compileCommand,
|
compileCommand,
|
||||||
disasmCommand,
|
disasmCommand,
|
||||||
|
|
@ -236,6 +266,8 @@ func init() {
|
||||||
stateTransitionCommand,
|
stateTransitionCommand,
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
blockBuilderCommand,
|
blockBuilderCommand,
|
||||||
|
eofParseCommand,
|
||||||
|
eofDumpCommand,
|
||||||
}
|
}
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
flags.MigrateGlobalFlags(ctx)
|
flags.MigrateGlobalFlags(ctx)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -51,7 +52,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),
|
Flags: slices.Concat(vmFlags, traceFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
// readGenesis will read the given JSON format genesis file and return
|
// readGenesis will read the given JSON format genesis file and return
|
||||||
|
|
@ -79,19 +80,30 @@ func readGenesis(genesisPath string) *core.Genesis {
|
||||||
}
|
}
|
||||||
|
|
||||||
type execStats struct {
|
type execStats struct {
|
||||||
time time.Duration // The execution time.
|
Time time.Duration `json:"time"` // The execution Time.
|
||||||
allocs int64 // The number of heap allocations during execution.
|
Allocs int64 `json:"allocs"` // The number of heap allocations during execution.
|
||||||
bytesAllocated int64 // The cumulative number of bytes allocated during execution.
|
BytesAllocated int64 `json:"bytesAllocated"` // The cumulative number of bytes allocated during execution.
|
||||||
|
GasUsed uint64 `json:"gasUsed"` // the amount of gas used during execution
|
||||||
}
|
}
|
||||||
|
|
||||||
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []byte, gasLeft uint64, stats execStats, err error) {
|
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, execStats, error) {
|
||||||
if bench {
|
if bench {
|
||||||
|
// Do one warm-up run
|
||||||
|
output, gasUsed, err := execFunc()
|
||||||
result := testing.Benchmark(func(b *testing.B) {
|
result := testing.Benchmark(func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
output, gasLeft, err = execFunc()
|
haveOutput, haveGasUsed, haveErr := execFunc()
|
||||||
|
if !bytes.Equal(haveOutput, output) {
|
||||||
|
b.Fatalf("output differs, have\n%x\nwant%x\n", haveOutput, output)
|
||||||
|
}
|
||||||
|
if haveGasUsed != gasUsed {
|
||||||
|
b.Fatalf("gas differs, have %v want%v", haveGasUsed, gasUsed)
|
||||||
|
}
|
||||||
|
if haveErr != err {
|
||||||
|
b.Fatalf("err differs, have %v want%v", haveErr, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get the average execution time from the benchmarking result.
|
// Get the average execution time from the benchmarking result.
|
||||||
// There are other useful stats here that could be reported.
|
// There are other useful stats here that could be reported.
|
||||||
stats.time = time.Duration(result.NsPerOp())
|
stats.time = time.Duration(result.NsPerOp())
|
||||||
|
|
@ -110,8 +122,19 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []by
|
||||||
stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
|
stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
|
||||||
stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc)
|
stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc)
|
||||||
}
|
}
|
||||||
|
var memStatsBefore, memStatsAfter goruntime.MemStats
|
||||||
return output, gasLeft, stats, err
|
goruntime.ReadMemStats(&memStatsBefore)
|
||||||
|
t0 := time.Now()
|
||||||
|
output, gasUsed, err := execFunc()
|
||||||
|
duration := time.Since(t0)
|
||||||
|
goruntime.ReadMemStats(&memStatsAfter)
|
||||||
|
stats := execStats{
|
||||||
|
Time: duration,
|
||||||
|
Allocs: int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs),
|
||||||
|
BytesAllocated: int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc),
|
||||||
|
GasUsed: gasUsed,
|
||||||
|
}
|
||||||
|
return output, stats, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(ctx *cli.Context) error {
|
func runCmd(ctx *cli.Context) error {
|
||||||
|
|
@ -284,12 +307,13 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
execFunc = func() ([]byte, uint64, error) {
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
return runtime.Call(receiver, input, &runtimeConfig)
|
output, gasLeft, err := runtime.Call(receiver, input, &runtimeConfig)
|
||||||
|
return output, initialGas - gasLeft, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bench := ctx.Bool(BenchFlag.Name)
|
bench := ctx.Bool(BenchFlag.Name)
|
||||||
output, leftOverGas, stats, err := timedExec(bench, execFunc)
|
output, stats, err := timedExec(bench, execFunc)
|
||||||
|
|
||||||
if ctx.Bool(DumpFlag.Name) {
|
if ctx.Bool(DumpFlag.Name) {
|
||||||
root, err := statedb.Commit(genesisConfig.Number, true)
|
root, err := statedb.Commit(genesisConfig.Number, true)
|
||||||
|
|
@ -320,7 +344,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
execution time: %v
|
execution time: %v
|
||||||
allocations: %d
|
allocations: %d
|
||||||
allocated bytes: %d
|
allocated bytes: %d
|
||||||
`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated)
|
`, stats.GasUsed, stats.Time, stats.Allocs, stats.BytesAllocated)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tracer == nil {
|
if tracer == nil {
|
||||||
|
|
|
||||||
|
|
@ -29,25 +29,50 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"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/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
forkFlag = &cli.StringFlag{
|
||||||
|
Name: "statetest.fork",
|
||||||
|
Usage: "The hard-fork to run the test against",
|
||||||
|
Category: flags.VMCategory,
|
||||||
|
}
|
||||||
|
idxFlag = &cli.IntFlag{
|
||||||
|
Name: "statetest.index",
|
||||||
|
Usage: "The index of the subtest to run",
|
||||||
|
Category: flags.VMCategory,
|
||||||
|
Value: -1, // default to select all subtest indices
|
||||||
|
}
|
||||||
|
testNameFlag = &cli.StringFlag{
|
||||||
|
Name: "statetest.name",
|
||||||
|
Usage: "The name of the state test to run",
|
||||||
|
Category: flags.VMCategory,
|
||||||
|
}
|
||||||
|
)
|
||||||
var stateTestCommand = &cli.Command{
|
var stateTestCommand = &cli.Command{
|
||||||
Action: stateTestCmd,
|
Action: stateTestCmd,
|
||||||
Name: "statetest",
|
Name: "statetest",
|
||||||
Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
|
Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
|
||||||
ArgsUsage: "<file>",
|
ArgsUsage: "<file>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
forkFlag,
|
||||||
|
idxFlag,
|
||||||
|
testNameFlag,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatetestResult contains the execution status after running a state test, any
|
// StatetestResult contains the execution status after running a state test, any
|
||||||
// error that might have occurred and a dump of the final state if requested.
|
// error that might have occurred and a dump of the final state if requested.
|
||||||
type StatetestResult struct {
|
type StatetestResult struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Pass bool `json:"pass"`
|
Pass bool `json:"pass"`
|
||||||
Root *common.Hash `json:"stateRoot,omitempty"`
|
Root *common.Hash `json:"stateRoot,omitempty"`
|
||||||
Fork string `json:"fork"`
|
Fork string `json:"fork"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
State *state.Dump `json:"state,omitempty"`
|
State *state.Dump `json:"state,omitempty"`
|
||||||
|
BenchStats *execStats `json:"benchStats,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func stateTestCmd(ctx *cli.Context) error {
|
func stateTestCmd(ctx *cli.Context) error {
|
||||||
|
|
@ -68,7 +93,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
// Load the test content from the input file
|
// Load the test content from the input file
|
||||||
if len(ctx.Args().First()) != 0 {
|
if len(ctx.Args().First()) != 0 {
|
||||||
return runStateTest(ctx.Args().First(), cfg, ctx.Bool(DumpFlag.Name))
|
return runStateTest(ctx, ctx.Args().First(), cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name))
|
||||||
}
|
}
|
||||||
// Read filenames from stdin and execute back-to-back
|
// Read filenames from stdin and execute back-to-back
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
|
@ -77,15 +102,48 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
if len(fname) == 0 {
|
if len(fname) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := runStateTest(fname, cfg, ctx.Bool(DumpFlag.Name)); err != nil {
|
if err := runStateTest(ctx, fname, cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stateTestCase struct {
|
||||||
|
name string
|
||||||
|
test tests.StateTest
|
||||||
|
st tests.StateSubtest
|
||||||
|
}
|
||||||
|
|
||||||
|
// collectMatchedSubtests returns test cases which match against provided filtering CLI parameters
|
||||||
|
func collectMatchedSubtests(ctx *cli.Context, testsByName map[string]tests.StateTest) []stateTestCase {
|
||||||
|
var res []stateTestCase
|
||||||
|
subtestName := ctx.String(testNameFlag.Name)
|
||||||
|
if subtestName != "" {
|
||||||
|
if subtest, ok := testsByName[subtestName]; ok {
|
||||||
|
testsByName := make(map[string]tests.StateTest)
|
||||||
|
testsByName[subtestName] = subtest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx := ctx.Int(idxFlag.Name)
|
||||||
|
fork := ctx.String(forkFlag.Name)
|
||||||
|
|
||||||
|
for key, test := range testsByName {
|
||||||
|
for _, st := range test.Subtests() {
|
||||||
|
if idx != -1 && st.Index != idx {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fork != "" && st.Fork != fork {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res = append(res, stateTestCase{name: key, st: st, test: test})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// runStateTest loads the state-test given by fname, and executes the test.
|
// runStateTest loads the state-test given by fname, and executes the test.
|
||||||
func runStateTest(fname string, cfg vm.Config, dump bool) error {
|
func runStateTest(ctx *cli.Context, fname string, cfg vm.Config, dump bool, bench bool) error {
|
||||||
src, err := os.ReadFile(fname)
|
src, err := os.ReadFile(fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -96,32 +154,38 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over all the tests, run them and aggregate the results
|
matchingTests := collectMatchedSubtests(ctx, testsByName)
|
||||||
results := make([]StatetestResult, 0, len(testsByName))
|
|
||||||
|
|
||||||
for key, test := range testsByName {
|
// Iterate over all the tests, run them and aggregate the results
|
||||||
for _, st := range test.Subtests() {
|
var results []StatetestResult
|
||||||
// Run the test and aggregate the result
|
for _, test := range matchingTests {
|
||||||
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
// Run the test and aggregate the result
|
||||||
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
|
result := &StatetestResult{Name: test.name, Fork: test.st.Fork, Pass: true}
|
||||||
var root common.Hash
|
test.test.Run(test.st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
|
||||||
if tstate.StateDB != nil {
|
var root common.Hash
|
||||||
root = tstate.StateDB.IntermediateRoot(false)
|
if tstate.StateDB != nil {
|
||||||
result.Root = &root
|
root = tstate.StateDB.IntermediateRoot(false)
|
||||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
result.Root = &root
|
||||||
if dump { // Dump any state to aid debugging
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||||
cpy, _ := state.New(root, tstate.StateDB.Database())
|
if dump { // Dump any state to aid debugging
|
||||||
dump := cpy.RawDump(nil)
|
cpy, _ := state.New(root, tstate.StateDB.Database())
|
||||||
result.State = &dump
|
dump := cpy.RawDump(nil)
|
||||||
}
|
result.State = &dump
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
// Test failed, mark as so
|
|
||||||
result.Pass, result.Error = false, err.Error()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// Test failed, mark as so
|
||||||
|
result.Pass, result.Error = false, err.Error()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if bench {
|
||||||
|
_, stats, _ := timedExec(true, func() ([]byte, uint64, error) {
|
||||||
|
_, _, gasUsed, _ := test.test.RunNoVerify(test.st, cfg, false, rawdb.HashScheme)
|
||||||
|
return nil, gasUsed, nil
|
||||||
})
|
})
|
||||||
results = append(results, *result)
|
result.BenchStats = &stats
|
||||||
}
|
}
|
||||||
|
results = append(results, *result)
|
||||||
}
|
}
|
||||||
|
|
||||||
out, _ := json.MarshalIndent(results, "", " ")
|
out, _ := json.MarshalIndent(results, "", " ")
|
||||||
|
|
|
||||||
19
cmd/evm/testdata/eof/eof_benches.txt
vendored
Normal file
19
cmd/evm/testdata/eof/eof_benches.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
1986
cmd/evm/testdata/eof/eof_corpus_0.txt
vendored
Normal file
1986
cmd/evm/testdata/eof/eof_corpus_0.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
350
cmd/evm/testdata/eof/eof_corpus_1.txt
vendored
Normal file
350
cmd/evm/testdata/eof/eof_corpus_1.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
2336
cmd/evm/testdata/eof/results.initcode.txt
vendored
Normal file
2336
cmd/evm/testdata/eof/results.initcode.txt
vendored
Normal file
File diff suppressed because it is too large
Load diff
2336
cmd/evm/testdata/eof/results.regular.txt
vendored
Normal file
2336
cmd/evm/testdata/eof/results.regular.txt
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -17,16 +17,19 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -192,7 +195,7 @@ nodes.
|
||||||
// makeAccountManager creates an account manager with backends
|
// makeAccountManager creates an account manager with backends
|
||||||
func makeAccountManager(ctx *cli.Context) *accounts.Manager {
|
func makeAccountManager(ctx *cli.Context) *accounts.Manager {
|
||||||
cfg := loadBaseConfig(ctx)
|
cfg := loadBaseConfig(ctx)
|
||||||
am := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: cfg.Node.InsecureUnlockAllowed})
|
am := accounts.NewManager(nil)
|
||||||
keydir, isEphemeral, err := cfg.Node.GetKeyStoreDir()
|
keydir, isEphemeral, err := cfg.Node.GetKeyStoreDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to get the keystore directory: %v", err)
|
utils.Fatalf("Failed to get the keystore directory: %v", err)
|
||||||
|
|
@ -221,72 +224,22 @@ func accountList(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// tries unlocking the specified account a few times.
|
// readPasswordFromFile reads the first line of the given file, trims line endings,
|
||||||
func unlockAccount(ks *keystore.KeyStore, address string, i int, passwords []string) (accounts.Account, string) {
|
// and returns the password and whether the reading was successful.
|
||||||
account, err := utils.MakeAddress(ks, address)
|
func readPasswordFromFile(path string) (string, bool) {
|
||||||
|
if path == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
text, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not list accounts: %v", err)
|
utils.Fatalf("Failed to read password file: %v", err)
|
||||||
}
|
}
|
||||||
|
lines := strings.Split(string(text), "\n")
|
||||||
for trials := 0; trials < 3; trials++ {
|
if len(lines) == 0 {
|
||||||
prompt := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", address, trials+1, 3)
|
return "", false
|
||||||
password := utils.GetPassPhraseWithList(prompt, false, i, passwords)
|
|
||||||
|
|
||||||
err = ks.Unlock(account, password)
|
|
||||||
if err == nil {
|
|
||||||
log.Info("Unlocked account", "address", account.Address.Hex())
|
|
||||||
return account, password
|
|
||||||
}
|
|
||||||
|
|
||||||
if err, ok := err.(*keystore.AmbiguousAddrError); ok {
|
|
||||||
log.Info("Unlocked account", "address", account.Address.Hex())
|
|
||||||
return ambiguousAddrRecovery(ks, err, password), password
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != keystore.ErrDecrypt {
|
|
||||||
// No need to prompt again if the error is not decryption-related.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// All trials expended to unlock account, bail out
|
// Sanitise DOS line endings.
|
||||||
utils.Fatalf("Failed to unlock account %s (%v)", address, err)
|
return strings.TrimRight(lines[0], "\r"), true
|
||||||
|
|
||||||
return accounts.Account{}, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrError, auth string) accounts.Account {
|
|
||||||
fmt.Printf("Multiple key files exist for address %x:\n", err.Addr)
|
|
||||||
|
|
||||||
for _, a := range err.Matches {
|
|
||||||
fmt.Println(" ", a.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Testing your password against all of them...")
|
|
||||||
|
|
||||||
var match *accounts.Account
|
|
||||||
|
|
||||||
for i, a := range err.Matches {
|
|
||||||
if e := ks.Unlock(a, auth); e == nil {
|
|
||||||
match = &err.Matches[i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if match == nil {
|
|
||||||
utils.Fatalf("None of the listed files could be unlocked.")
|
|
||||||
return accounts.Account{}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Your password unlocked %s\n", match.URL)
|
|
||||||
fmt.Println("In order to avoid this warning, you need to remove the following duplicate key files:")
|
|
||||||
|
|
||||||
for _, a := range err.Matches {
|
|
||||||
if a != *match {
|
|
||||||
fmt.Println(" ", a.URL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *match
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// accountCreate creates a new account into the keystore defined by the CLI flags.
|
// accountCreate creates a new account into the keystore defined by the CLI flags.
|
||||||
|
|
@ -308,8 +261,10 @@ func accountCreate(ctx *cli.Context) error {
|
||||||
scryptP = keystore.LightScryptP
|
scryptP = keystore.LightScryptP
|
||||||
}
|
}
|
||||||
|
|
||||||
password := utils.GetPassPhraseWithList("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))
|
password, ok := readPasswordFromFile(ctx.Path(utils.PasswordFileFlag.Name))
|
||||||
|
if !ok {
|
||||||
|
password = utils.GetPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true)
|
||||||
|
}
|
||||||
account, err := keystore.StoreKey(keydir, password, scryptN, scryptP)
|
account, err := keystore.StoreKey(keydir, password, scryptN, scryptP)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -342,11 +297,23 @@ func accountUpdate(ctx *cli.Context) error {
|
||||||
ks := backends[0].(*keystore.KeyStore)
|
ks := backends[0].(*keystore.KeyStore)
|
||||||
|
|
||||||
for _, addr := range ctx.Args().Slice() {
|
for _, addr := range ctx.Args().Slice() {
|
||||||
account, oldPassword := unlockAccount(ks, addr, 0, nil)
|
if !common.IsHexAddress(addr) {
|
||||||
newPassword := utils.GetPassPhraseWithList("Please give a new password. Do not forget this password.", true, 0, nil)
|
return errors.New("address must be specified in hexadecimal form")
|
||||||
|
}
|
||||||
if err := ks.Update(account, oldPassword, newPassword); err != nil {
|
account := accounts.Account{Address: common.HexToAddress(addr)}
|
||||||
utils.Fatalf("Could not update the account: %v", err)
|
newPassword := utils.GetPassPhrase("Please give a NEW password. Do not forget this password.", true)
|
||||||
|
updateFn := func(attempt int) error {
|
||||||
|
prompt := fmt.Sprintf("Please provide the OLD password for account %s | Attempt %d/%d", addr, attempt+1, 3)
|
||||||
|
password := utils.GetPassPhrase(prompt, false)
|
||||||
|
return ks.Update(account, password, newPassword)
|
||||||
|
}
|
||||||
|
// let user attempt unlock thrice.
|
||||||
|
err := updateFn(0)
|
||||||
|
for attempts := 1; attempts < 3 && errors.Is(err, keystore.ErrDecrypt); attempts++ {
|
||||||
|
err = updateFn(attempts)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not update account: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,11 +337,12 @@ func importWallet(ctx *cli.Context) error {
|
||||||
if len(backends) == 0 {
|
if len(backends) == 0 {
|
||||||
utils.Fatalf("Keystore is not available")
|
utils.Fatalf("Keystore is not available")
|
||||||
}
|
}
|
||||||
|
password, ok := readPasswordFromFile(ctx.Path(utils.PasswordFileFlag.Name))
|
||||||
|
if !ok {
|
||||||
|
password = utils.GetPassPhrase("", false)
|
||||||
|
}
|
||||||
ks := backends[0].(*keystore.KeyStore)
|
ks := backends[0].(*keystore.KeyStore)
|
||||||
passphrase := utils.GetPassPhraseWithList("", false, 0, utils.MakePasswordList(ctx))
|
acct, err := ks.ImportPreSaleKey(keyJSON, password)
|
||||||
|
|
||||||
acct, err := ks.ImportPreSaleKey(keyJSON, passphrase)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -402,9 +370,11 @@ func accountImport(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
ks := backends[0].(*keystore.KeyStore)
|
ks := backends[0].(*keystore.KeyStore)
|
||||||
passphrase := utils.GetPassPhraseWithList("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))
|
password, ok := readPasswordFromFile(ctx.Path(utils.PasswordFileFlag.Name))
|
||||||
|
if !ok {
|
||||||
acct, err := ks.ImportECDSA(key, passphrase)
|
password = utils.GetPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true)
|
||||||
|
}
|
||||||
|
acct, err := ks.ImportECDSA(key, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not create the account: %v", err)
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cespare/cp"
|
"github.com/cespare/cp"
|
||||||
|
|
@ -117,7 +116,6 @@ func TestAccountImport(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
test := test
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
importAccountWithExpect(t, test.key, test.output)
|
importAccountWithExpect(t, test.key, test.output)
|
||||||
|
|
@ -183,12 +181,12 @@ func TestAccountUpdate(t *testing.T) {
|
||||||
"f466859ead1932d743d622cb74fc058882e8648a")
|
"f466859ead1932d743d622cb74fc058882e8648a")
|
||||||
defer geth.ExpectExit()
|
defer geth.ExpectExit()
|
||||||
geth.Expect(`
|
geth.Expect(`
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
Please give a NEW password. Do not forget this password.
|
||||||
!! Unsupported terminal, password will be echoed.
|
!! Unsupported terminal, password will be echoed.
|
||||||
Password: {{.InputLine "foobar"}}
|
|
||||||
Please give a new password. Do not forget this password.
|
|
||||||
Password: {{.InputLine "foobar2"}}
|
Password: {{.InputLine "foobar2"}}
|
||||||
Repeat password: {{.InputLine "foobar2"}}
|
Repeat password: {{.InputLine "foobar2"}}
|
||||||
|
Please provide the OLD password for account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
||||||
|
Password: {{.InputLine "foobar"}}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,173 +216,3 @@ Password: {{.InputLine "wrong"}}
|
||||||
Fatal: could not decrypt key with given password
|
Fatal: could not decrypt key with given password
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnlockFlag(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')")
|
|
||||||
geth.Expect(`
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
|
||||||
!! Unsupported terminal, password will be echoed.
|
|
||||||
Password: {{.InputLine "foobar"}}
|
|
||||||
undefined
|
|
||||||
`)
|
|
||||||
geth.ExpectExit()
|
|
||||||
|
|
||||||
wantMessages := []string{
|
|
||||||
"Unlocked account",
|
|
||||||
"=0xf466859eAD1932D743d622CB74FC058882E8648A",
|
|
||||||
}
|
|
||||||
for _, m := range wantMessages {
|
|
||||||
if !strings.Contains(geth.StderrText(), m) {
|
|
||||||
t.Errorf("stderr text does not contain %q", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnlockFlagWrongPassword(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')")
|
|
||||||
|
|
||||||
defer geth.ExpectExit()
|
|
||||||
geth.Expect(`
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
|
||||||
!! Unsupported terminal, password will be echoed.
|
|
||||||
Password: {{.InputLine "wrong1"}}
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 2/3
|
|
||||||
Password: {{.InputLine "wrong2"}}
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 3/3
|
|
||||||
Password: {{.InputLine "wrong3"}}
|
|
||||||
Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could not decrypt key with given password)
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/ethereum/go-ethereum/issues/1785
|
|
||||||
func TestUnlockFlagMultiIndex(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
|
|
||||||
|
|
||||||
geth.Expect(`
|
|
||||||
Unlocking account 0 | Attempt 1/3
|
|
||||||
!! Unsupported terminal, password will be echoed.
|
|
||||||
Password: {{.InputLine "foobar"}}
|
|
||||||
Unlocking account 2 | Attempt 1/3
|
|
||||||
Password: {{.InputLine "foobar"}}
|
|
||||||
undefined
|
|
||||||
`)
|
|
||||||
geth.ExpectExit()
|
|
||||||
|
|
||||||
wantMessages := []string{
|
|
||||||
"Unlocked account",
|
|
||||||
"=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
|
|
||||||
"=0x289d485D9771714CCe91D3393D764E1311907ACc",
|
|
||||||
}
|
|
||||||
for _, m := range wantMessages {
|
|
||||||
if !strings.Contains(geth.StderrText(), m) {
|
|
||||||
t.Errorf("stderr text does not contain %q", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnlockFlagPasswordFile(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password", "testdata/passwords.txt", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
|
|
||||||
|
|
||||||
geth.Expect(`
|
|
||||||
undefined
|
|
||||||
`)
|
|
||||||
geth.ExpectExit()
|
|
||||||
|
|
||||||
wantMessages := []string{
|
|
||||||
"Unlocked account",
|
|
||||||
"=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
|
|
||||||
"=0x289d485D9771714CCe91D3393D764E1311907ACc",
|
|
||||||
}
|
|
||||||
for _, m := range wantMessages {
|
|
||||||
if !strings.Contains(geth.StderrText(), m) {
|
|
||||||
t.Errorf("stderr text does not contain %q", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password",
|
|
||||||
"testdata/wrong-passwords.txt", "--unlock", "0,2")
|
|
||||||
defer geth.ExpectExit()
|
|
||||||
geth.Expect(`
|
|
||||||
Fatal: Failed to unlock account 0 (could not decrypt key with given password)
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnlockFlagAmbiguous(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
|
|
||||||
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
|
|
||||||
store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
|
|
||||||
"console", "--exec", "loadScript('testdata/empty.js')")
|
|
||||||
defer geth.ExpectExit()
|
|
||||||
|
|
||||||
// Helper for the expect template, returns absolute keystore path.
|
|
||||||
geth.SetTemplateFunc("keypath", func(file string) string {
|
|
||||||
abs, _ := filepath.Abs(filepath.Join(store, file))
|
|
||||||
return abs
|
|
||||||
})
|
|
||||||
geth.Expect(`
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
|
||||||
!! Unsupported terminal, password will be echoed.
|
|
||||||
Password: {{.InputLine "foobar"}}
|
|
||||||
Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
|
|
||||||
keystore://{{keypath "1"}}
|
|
||||||
keystore://{{keypath "2"}}
|
|
||||||
Testing your password against all of them...
|
|
||||||
Your password unlocked keystore://{{keypath "1"}}
|
|
||||||
In order to avoid this warning, you need to remove the following duplicate key files:
|
|
||||||
keystore://{{keypath "2"}}
|
|
||||||
undefined
|
|
||||||
`)
|
|
||||||
geth.ExpectExit()
|
|
||||||
|
|
||||||
wantMessages := []string{
|
|
||||||
"Unlocked account",
|
|
||||||
"=0xf466859eAD1932D743d622CB74FC058882E8648A",
|
|
||||||
}
|
|
||||||
for _, m := range wantMessages {
|
|
||||||
if !strings.Contains(geth.StderrText(), m) {
|
|
||||||
t.Errorf("stderr text does not contain %q", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
|
|
||||||
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
|
|
||||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
|
|
||||||
store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a")
|
|
||||||
|
|
||||||
defer geth.ExpectExit()
|
|
||||||
|
|
||||||
// Helper for the expect template, returns absolute keystore path.
|
|
||||||
geth.SetTemplateFunc("keypath", func(file string) string {
|
|
||||||
abs, _ := filepath.Abs(filepath.Join(store, file))
|
|
||||||
return abs
|
|
||||||
})
|
|
||||||
geth.Expect(`
|
|
||||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
|
||||||
!! Unsupported terminal, password will be echoed.
|
|
||||||
Password: {{.InputLine "wrong"}}
|
|
||||||
Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
|
|
||||||
keystore://{{keypath "1"}}
|
|
||||||
keystore://{{keypath "2"}}
|
|
||||||
Testing your password against all of them...
|
|
||||||
Fatal: None of the listed files could be unlocked.
|
|
||||||
`)
|
|
||||||
geth.ExpectExit()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -39,7 +40,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -51,7 +51,7 @@ 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{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CachePreimagesFlag,
|
utils.CachePreimagesFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
|
|
@ -78,7 +78,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Import a blockchain file",
|
Usage: "Import a blockchain file",
|
||||||
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.GCModeFlag,
|
utils.GCModeFlag,
|
||||||
|
|
@ -117,7 +117,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Export blockchain into file",
|
Usage: "Export blockchain into file",
|
||||||
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
|
|
@ -133,7 +133,7 @@ be gzipped.`,
|
||||||
Name: "import-history",
|
Name: "import-history",
|
||||||
Usage: "Import an Era archive",
|
Usage: "Import an Era archive",
|
||||||
ArgsUsage: "<dir>",
|
ArgsUsage: "<dir>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
},
|
},
|
||||||
utils.DatabaseFlags,
|
utils.DatabaseFlags,
|
||||||
|
|
@ -149,7 +149,7 @@ from Era archives.
|
||||||
Name: "export-history",
|
Name: "export-history",
|
||||||
Usage: "Export blockchain history to Era archives",
|
Usage: "Export blockchain history to Era archives",
|
||||||
ArgsUsage: "<dir> <first> <last>",
|
ArgsUsage: "<dir> <first> <last>",
|
||||||
Flags: flags.Merge(utils.DatabaseFlags),
|
Flags: slices.Concat(utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The export-history command will export blocks and their corresponding receipts
|
The export-history command will export blocks and their corresponding receipts
|
||||||
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
||||||
|
|
@ -160,7 +160,7 @@ into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
||||||
Name: "import-preimages",
|
Name: "import-preimages",
|
||||||
Usage: "Import the preimage database from an RLP stream",
|
Usage: "Import the preimage database from an RLP stream",
|
||||||
ArgsUsage: "<datafile>",
|
ArgsUsage: "<datafile>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
|
|
@ -175,7 +175,7 @@ It's deprecated, please use "geth db import" instead.
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump a specific block from storage",
|
Usage: "Dump a specific block from storage",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.IterativeOutputFlag,
|
utils.IterativeOutputFlag,
|
||||||
utils.ExcludeCodeFlag,
|
utils.ExcludeCodeFlag,
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
@ -46,7 +47,6 @@ 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/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/naoina/toml"
|
"github.com/naoina/toml"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
@ -58,7 +58,7 @@ var (
|
||||||
Name: "dumpconfig",
|
Name: "dumpconfig",
|
||||||
Usage: "Export configuration values in a TOML format",
|
Usage: "Export configuration values in a TOML format",
|
||||||
ArgsUsage: "<dumpfile (optional)>",
|
ArgsUsage: "<dumpfile (optional)>",
|
||||||
Flags: flags.Merge(nodeFlags, rpcFlags),
|
Flags: slices.Concat(nodeFlags, rpcFlags),
|
||||||
Description: `Export configuration values in TOML format (to stdout by default).`,
|
Description: `Export configuration values in TOML format (to stdout by default).`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,11 +134,10 @@ func defaultNodeConfig() node.Config {
|
||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
cfg := node.DefaultConfig
|
cfg := node.DefaultConfig
|
||||||
cfg.Name = clientIdentifier
|
cfg.Name = clientIdentifier
|
||||||
cfg.Version = params.VersionWithCommit(git.Commit, git.Date)
|
cfg.Version = version.WithCommit(git.Commit, git.Date)
|
||||||
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
||||||
cfg.WSModules = append(cfg.WSModules, "eth")
|
cfg.WSModules = append(cfg.WSModules, "eth")
|
||||||
cfg.IPCPath = clientIdentifier + ".ipc"
|
cfg.IPCPath = clientIdentifier + ".ipc"
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,7 +261,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||||
// Start blsync mode.
|
// Start blsync mode.
|
||||||
srv := rpc.NewServer("", 0, 0)
|
srv := rpc.NewServer("", 0, 0)
|
||||||
srv.RegisterName("engine", catalyst.NewConsensusAPI(eth))
|
srv.RegisterName("engine", catalyst.NewConsensusAPI(eth))
|
||||||
blsyncer := blsync.NewClient(ctx)
|
blsyncer := blsync.NewClient(utils.MakeBeaconLightConfig(ctx))
|
||||||
blsyncer.SetEngineRPC(rpc.DialInProc(srv))
|
blsyncer.SetEngineRPC(rpc.DialInProc(srv))
|
||||||
stack.RegisterLifecycle(blsyncer)
|
stack.RegisterLifecycle(blsyncer)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"slices"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/urfave/cli/v2"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -37,7 +35,7 @@ var (
|
||||||
Action: localConsole,
|
Action: localConsole,
|
||||||
Name: "console",
|
Name: "console",
|
||||||
Usage: "Start an interactive JavaScript environment",
|
Usage: "Start an interactive JavaScript environment",
|
||||||
Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags),
|
Flags: slices.Concat(nodeFlags, rpcFlags, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
|
|
@ -49,7 +47,7 @@ See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`,
|
||||||
Name: "attach",
|
Name: "attach",
|
||||||
Usage: "Start an interactive JavaScript environment (connect to node)",
|
Usage: "Start an interactive JavaScript environment (connect to node)",
|
||||||
ArgsUsage: "[endpoint]",
|
ArgsUsage: "[endpoint]",
|
||||||
Flags: flags.Merge([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags),
|
Flags: slices.Concat([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
|
|
@ -62,7 +60,7 @@ This command allows to open a console on a running geth node.`,
|
||||||
Name: "js",
|
Name: "js",
|
||||||
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
||||||
ArgsUsage: "<jsfile> [jsfile...]",
|
ArgsUsage: "<jsfile> [jsfile...]",
|
||||||
Flags: flags.Merge(nodeFlags, consoleFlags),
|
Flags: slices.Concat(nodeFlags, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
||||||
JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`,
|
JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`,
|
||||||
|
|
@ -177,7 +175,7 @@ func remoteConsole(ctx *cli.Context) error {
|
||||||
func ephemeralConsole(ctx *cli.Context) error {
|
func ephemeralConsole(ctx *cli.Context) error {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
for _, file := range ctx.Args().Slice() {
|
for _, file := range ctx.Args().Slice() {
|
||||||
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
|
b.WriteString(fmt.Sprintf("loadScript('%s');", file))
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -61,7 +61,7 @@ func TestConsoleWelcome(t *testing.T) {
|
||||||
geth.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
geth.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
||||||
geth.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
geth.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
||||||
geth.SetTemplateFunc("gover", runtime.Version)
|
geth.SetTemplateFunc("gover", runtime.Version)
|
||||||
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
geth.SetTemplateFunc("gethver", func() string { return version.WithCommit("", "") })
|
||||||
geth.SetTemplateFunc("niltime", func() string {
|
geth.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
|
|
@ -131,7 +131,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
|
||||||
attach.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
attach.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
||||||
attach.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
attach.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
||||||
attach.SetTemplateFunc("gover", runtime.Version)
|
attach.SetTemplateFunc("gover", runtime.Version)
|
||||||
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
attach.SetTemplateFunc("gethver", func() string { return version.WithCommit("", "") })
|
||||||
attach.SetTemplateFunc("niltime", func() string {
|
attach.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -36,7 +37,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -60,7 +60,7 @@ var (
|
||||||
Name: "removedb",
|
Name: "removedb",
|
||||||
Usage: "Remove blockchain and state databases",
|
Usage: "Remove blockchain and state databases",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: flags.Merge(utils.DatabaseFlags,
|
Flags: slices.Concat(utils.DatabaseFlags,
|
||||||
[]cli.Flag{removeStateDataFlag, removeChainDataFlag}),
|
[]cli.Flag{removeStateDataFlag, removeChainDataFlag}),
|
||||||
Description: `
|
Description: `
|
||||||
Remove blockchain and state databases`,
|
Remove blockchain and state databases`,
|
||||||
|
|
@ -89,7 +89,7 @@ Remove blockchain and state databases`,
|
||||||
Action: inspect,
|
Action: inspect,
|
||||||
Name: "inspect",
|
Name: "inspect",
|
||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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",
|
||||||
|
|
@ -99,7 +99,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.DatabaseFlags),
|
Flags: slices.Concat(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
|
||||||
|
|
@ -109,7 +109,7 @@ a data corruption.`,
|
||||||
Action: dbStats,
|
Action: dbStats,
|
||||||
Name: "stats",
|
Name: "stats",
|
||||||
Usage: "Print leveldb statistics",
|
Usage: "Print leveldb statistics",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ a data corruption.`,
|
||||||
Action: dbCompact,
|
Action: dbCompact,
|
||||||
Name: "compact",
|
Name: "compact",
|
||||||
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
|
|
@ -131,7 +131,7 @@ corruption if it is aborted during execution'!`,
|
||||||
Name: "get",
|
Name: "get",
|
||||||
Usage: "Show the value of a database key",
|
Usage: "Show the value of a database key",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.",
|
||||||
|
|
@ -141,7 +141,7 @@ corruption if it is aborted during execution'!`,
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.
|
||||||
|
|
@ -152,7 +152,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "put",
|
Name: "put",
|
||||||
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.
|
||||||
|
|
@ -163,7 +163,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "dumptrie",
|
Name: "dumptrie",
|
||||||
Usage: "Show the storage key/values of a given storage trie",
|
Usage: "Show the storage key/values of a given storage trie",
|
||||||
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: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.",
|
||||||
|
|
@ -173,7 +173,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "freezer-index",
|
Name: "freezer-index",
|
||||||
Usage: "Dump out the index of a specific freezer table",
|
Usage: "Dump out the index of a specific freezer table",
|
||||||
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
|
|
@ -183,7 +183,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Imports leveldb-data from an exported RLP dump.",
|
Usage: "Imports leveldb-data from an exported RLP dump.",
|
||||||
ArgsUsage: "<dumpfile> <start (optional)",
|
ArgsUsage: "<dumpfile> <start (optional)",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.",
|
||||||
|
|
@ -193,7 +193,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
||||||
ArgsUsage: "<type> <dumpfile>",
|
ArgsUsage: "<type> <dumpfile>",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, 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.",
|
||||||
|
|
@ -202,7 +202,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Action: showMetaData,
|
Action: showMetaData,
|
||||||
Name: "metadata",
|
Name: "metadata",
|
||||||
Usage: "Shows metadata about the chain status.",
|
Usage: "Shows metadata about the chain status.",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "Shows metadata about the chain status.",
|
Description: "Shows metadata about the chain status.",
|
||||||
|
|
@ -212,7 +212,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "inspect-history",
|
Name: "inspect-history",
|
||||||
Usage: "Inspect the state history within block range",
|
Usage: "Inspect the state history within block range",
|
||||||
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
&cli.Uint64Flag{
|
&cli.Uint64Flag{
|
||||||
Name: "start",
|
Name: "start",
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ var customGenesisTests = []struct {
|
||||||
query string
|
query string
|
||||||
result string
|
result string
|
||||||
}{
|
}{
|
||||||
// Genesis file with an empty chain configuration (ensure missing fields work)
|
// Genesis file with a mostly-empty chain configuration (ensure missing fields work)
|
||||||
{
|
{
|
||||||
genesis: `{
|
genesis: `{
|
||||||
"alloc" : {},
|
"alloc" : {},
|
||||||
|
|
@ -41,8 +41,8 @@ var customGenesisTests = []struct {
|
||||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"timestamp" : "0x00",
|
"timestamp" : "0x00",
|
||||||
"config" : {
|
"config": {
|
||||||
"terminalTotalDifficultyPassed": true
|
"terminalTotalDifficulty": 0
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
query: "eth.getBlock(0).nonce",
|
query: "eth.getBlock(0).nonce",
|
||||||
|
|
@ -64,7 +64,7 @@ var customGenesisTests = []struct {
|
||||||
"homesteadBlock" : 42,
|
"homesteadBlock" : 42,
|
||||||
"daoForkBlock" : 141,
|
"daoForkBlock" : 141,
|
||||||
"daoForkSupport" : true,
|
"daoForkSupport" : true,
|
||||||
"terminalTotalDifficultyPassed" : true
|
"terminalTotalDifficulty": 0
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
query: "eth.getBlock(0).nonce",
|
query: "eth.getBlock(0).nonce",
|
||||||
|
|
@ -117,8 +117,8 @@ func TestCustomBackend(t *testing.T) {
|
||||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"timestamp" : "0x00",
|
"timestamp" : "0x00",
|
||||||
"config" : {
|
"config": {
|
||||||
"terminalTotalDifficultyPassed": true
|
"terminalTotalDifficulty": 0
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
type backendTest struct {
|
type backendTest struct {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -72,7 +73,7 @@ var (
|
||||||
utils.SmartCardDaemonPathFlag,
|
utils.SmartCardDaemonPathFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
utils.EnablePersonal,
|
utils.EnablePersonal, // deprecated
|
||||||
utils.TxPoolLocalsFlag,
|
utils.TxPoolLocalsFlag,
|
||||||
utils.TxPoolNoLocalsFlag,
|
utils.TxPoolNoLocalsFlag,
|
||||||
utils.TxPoolJournalFlag,
|
utils.TxPoolJournalFlag,
|
||||||
|
|
@ -259,7 +260,7 @@ func init() {
|
||||||
}
|
}
|
||||||
sort.Sort(cli.CommandsByName(app.Commands))
|
sort.Sort(cli.CommandsByName(app.Commands))
|
||||||
|
|
||||||
app.Flags = flags.Merge(
|
app.Flags = slices.Concat(
|
||||||
nodeFlags,
|
nodeFlags,
|
||||||
rpcFlags,
|
rpcFlags,
|
||||||
consoleFlags,
|
consoleFlags,
|
||||||
|
|
@ -390,8 +391,9 @@ func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
|
||||||
// Start up the node itself
|
// Start up the node itself
|
||||||
utils.StartNode(ctx, stack, isConsole)
|
utils.StartNode(ctx, stack, isConsole)
|
||||||
|
|
||||||
// Unlock any account specifically requested
|
if ctx.IsSet(utils.UnlockedAccountFlag.Name) {
|
||||||
unlockAccounts(ctx, stack)
|
log.Warn(`The "unlock" flag has been deprecated and has no effect`)
|
||||||
|
}
|
||||||
|
|
||||||
// Register wallet event handlers to open and auto-derive wallets
|
// Register wallet event handlers to open and auto-derive wallets
|
||||||
events := make(chan accounts.WalletEvent, 16)
|
events := make(chan accounts.WalletEvent, 16)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/version"
|
"github.com/ethereum/go-ethereum/internal/version"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -74,8 +74,7 @@ func printVersion(ctx *cli.Context) error {
|
||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
|
|
||||||
fmt.Println(strings.Title(clientIdentifier))
|
fmt.Println(strings.Title(clientIdentifier))
|
||||||
fmt.Println("Version:", params.VersionWithMeta)
|
fmt.Println("Version:", version.WithMeta)
|
||||||
|
|
||||||
if git.Commit != "" {
|
if git.Commit != "" {
|
||||||
fmt.Println("Git Commit:", git.Commit)
|
fmt.Println("Git Commit:", git.Commit)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
|
@ -32,7 +33,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -50,7 +50,7 @@ var (
|
||||||
Usage: "Prune stale ethereum state data based on the snapshot",
|
Usage: "Prune stale ethereum state data based on the snapshot",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: pruneState,
|
Action: pruneState,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.BloomFilterSizeFlag,
|
utils.BloomFilterSizeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
|
|
@ -70,7 +70,7 @@ WARNING: it's only supported in hash mode(--state.scheme=hash)".
|
||||||
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.DatabaseFlags),
|
Flags: slices.Concat(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
|
||||||
|
|
@ -83,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.DatabaseFlags),
|
Flags: slices.Concat(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.
|
||||||
|
|
@ -94,7 +94,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
Usage: "Check all snapshot layers for the specific account",
|
Usage: "Check all snapshot layers for the specific account",
|
||||||
ArgsUsage: "<address | hash>",
|
ArgsUsage: "<address | hash>",
|
||||||
Action: checkAccount,
|
Action: checkAccount,
|
||||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: slices.Concat(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.
|
||||||
|
|
@ -105,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.DatabaseFlags),
|
Flags: slices.Concat(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
|
||||||
|
|
@ -120,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.DatabaseFlags),
|
Flags: slices.Concat(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
|
||||||
|
|
@ -136,7 +136,7 @@ It's also usable without snapshot enabled.
|
||||||
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
Action: dumpState,
|
Action: dumpState,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.ExcludeCodeFlag,
|
utils.ExcludeCodeFlag,
|
||||||
utils.ExcludeStorageFlag,
|
utils.ExcludeStorageFlag,
|
||||||
utils.StartKeyFlag,
|
utils.StartKeyFlag,
|
||||||
|
|
@ -457,7 +457,7 @@ 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)
|
reader, err := triedb.NodeReader(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("State is non-existent", "root", root)
|
log.Error("State is non-existent", "root", root)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
2
cmd/geth/testdata/clique.json
vendored
2
cmd/geth/testdata/clique.json
vendored
|
|
@ -8,7 +8,7 @@
|
||||||
"byzantiumBlock": 0,
|
"byzantiumBlock": 0,
|
||||||
"constantinopleBlock": 0,
|
"constantinopleBlock": 0,
|
||||||
"petersburgBlock": 0,
|
"petersburgBlock": 0,
|
||||||
"terminalTotalDifficultyPassed": true,
|
"terminalTotalDifficulty": 0,
|
||||||
"clique": {
|
"clique": {
|
||||||
"period": 5,
|
"period": 5,
|
||||||
"epoch": 30000
|
"epoch": 30000
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-verkle"
|
"github.com/ethereum/go-verkle"
|
||||||
cli "github.com/urfave/cli/v2"
|
cli "github.com/urfave/cli/v2"
|
||||||
|
|
@ -45,7 +45,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.DatabaseFlags),
|
Flags: slices.Concat(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.
|
||||||
|
|
@ -56,7 +56,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.DatabaseFlags),
|
Flags: slices.Concat(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>.
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,6 @@ func TestKeyID(t *testing.T) {
|
||||||
{"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"},
|
{"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := keyID(tt.args.id); got != tt.want {
|
if got := keyID(tt.args.id); got != tt.want {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import (
|
||||||
bparams "github.com/ethereum/go-ethereum/beacon/params"
|
bparams "github.com/ethereum/go-ethereum/beacon/params"
|
||||||
"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/blobpool"
|
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||||
|
|
@ -190,12 +191,6 @@ var (
|
||||||
Usage: "Custom node name",
|
Usage: "Custom node name",
|
||||||
Category: flags.NetworkingCategory,
|
Category: flags.NetworkingCategory,
|
||||||
}
|
}
|
||||||
DocRootFlag = &flags.DirectoryFlag{
|
|
||||||
Name: "docroot",
|
|
||||||
Usage: "Document Root for HTTPClient file scheme",
|
|
||||||
Value: flags.DirectoryString(flags.HomeDir()),
|
|
||||||
Category: flags.APICategory,
|
|
||||||
}
|
|
||||||
ExitWhenSyncedFlag = &cli.BoolFlag{
|
ExitWhenSyncedFlag = &cli.BoolFlag{
|
||||||
Name: "exitwhensynced",
|
Name: "exitwhensynced",
|
||||||
Usage: "Exits after block synchronisation completes",
|
Usage: "Exits after block synchronisation completes",
|
||||||
|
|
@ -231,8 +226,7 @@ var (
|
||||||
Value: 0,
|
Value: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultSyncMode = ethconfig.Defaults.SyncMode
|
SnapshotFlag = &cli.BoolFlag{
|
||||||
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,
|
||||||
|
|
@ -264,10 +258,10 @@ 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{
|
SyncModeFlag = &cli.StringFlag{
|
||||||
Name: "syncmode",
|
Name: "syncmode",
|
||||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||||
Value: &defaultSyncMode,
|
Value: ethconfig.Defaults.SyncMode.String(),
|
||||||
Category: flags.StateCategory,
|
Category: flags.StateCategory,
|
||||||
}
|
}
|
||||||
GCModeFlag = &cli.StringFlag{
|
GCModeFlag = &cli.StringFlag{
|
||||||
|
|
@ -340,7 +334,7 @@ var (
|
||||||
Usage: "Target EL engine API URL",
|
Usage: "Target EL engine API URL",
|
||||||
Category: flags.BeaconCategory,
|
Category: flags.BeaconCategory,
|
||||||
}
|
}
|
||||||
BlsyncJWTSecretFlag = &cli.StringFlag{
|
BlsyncJWTSecretFlag = &flags.DirectoryFlag{
|
||||||
Name: "blsync.jwtsecret",
|
Name: "blsync.jwtsecret",
|
||||||
Usage: "Path to a JWT secret to use for target engine API endpoint",
|
Usage: "Path to a JWT secret to use for target engine API endpoint",
|
||||||
Category: flags.BeaconCategory,
|
Category: flags.BeaconCategory,
|
||||||
|
|
@ -544,12 +538,6 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account settings
|
// Account settings
|
||||||
UnlockedAccountFlag = &cli.StringFlag{
|
|
||||||
Name: "unlock",
|
|
||||||
Usage: "Comma separated list of accounts to unlock",
|
|
||||||
Value: "",
|
|
||||||
Category: flags.AccountCategory,
|
|
||||||
}
|
|
||||||
PasswordFileFlag = &cli.PathFlag{
|
PasswordFileFlag = &cli.PathFlag{
|
||||||
Name: "password",
|
Name: "password",
|
||||||
Usage: "Password file to use for non-interactive password input",
|
Usage: "Password file to use for non-interactive password input",
|
||||||
|
|
@ -562,12 +550,6 @@ var (
|
||||||
Value: "",
|
Value: "",
|
||||||
Category: flags.AccountCategory,
|
Category: flags.AccountCategory,
|
||||||
}
|
}
|
||||||
InsecureUnlockAllowedFlag = &cli.BoolFlag{
|
|
||||||
Name: "allow-insecure-unlock",
|
|
||||||
Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
|
|
||||||
Category: flags.AccountCategory,
|
|
||||||
}
|
|
||||||
|
|
||||||
// EVM settings
|
// EVM settings
|
||||||
VMEnableDebugFlag = &cli.BoolFlag{
|
VMEnableDebugFlag = &cli.BoolFlag{
|
||||||
Name: "vmdebug",
|
Name: "vmdebug",
|
||||||
|
|
@ -582,6 +564,7 @@ var (
|
||||||
VMTraceJsonConfigFlag = &cli.StringFlag{
|
VMTraceJsonConfigFlag = &cli.StringFlag{
|
||||||
Name: "vmtrace.jsonconfig",
|
Name: "vmtrace.jsonconfig",
|
||||||
Usage: "Tracer configuration (JSON)",
|
Usage: "Tracer configuration (JSON)",
|
||||||
|
Value: "{}",
|
||||||
Category: flags.VMCategory,
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
// API options.
|
// API options.
|
||||||
|
|
@ -779,11 +762,6 @@ var (
|
||||||
Value: node.DefaultConfig.BatchResponseMaxSize,
|
Value: node.DefaultConfig.BatchResponseMaxSize,
|
||||||
Category: flags.APICategory,
|
Category: flags.APICategory,
|
||||||
}
|
}
|
||||||
EnablePersonal = &cli.BoolFlag{
|
|
||||||
Name: "rpc.enabledeprecatedpersonal",
|
|
||||||
Usage: "Enables the (deprecated) personal namespace",
|
|
||||||
Category: flags.APICategory,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Network Settings
|
// Network Settings
|
||||||
MaxPeersFlag = &cli.IntFlag{
|
MaxPeersFlag = &cli.IntFlag{
|
||||||
|
|
@ -1333,33 +1311,6 @@ func MakeDatabaseHandles(max int) int {
|
||||||
return int(raised / 2) // Leave half for networking and other stuff
|
return int(raised / 2) // Leave half for networking and other stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeAddress converts an account specified directly as a hex encoded string or
|
|
||||||
// a key index in the key store to an internal account representation.
|
|
||||||
func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
|
|
||||||
// If the specified account is a valid address, return it
|
|
||||||
if common.IsHexAddress(account) {
|
|
||||||
return accounts.Account{Address: common.HexToAddress(account)}, nil
|
|
||||||
}
|
|
||||||
// Otherwise try to interpret the account as a keystore index
|
|
||||||
index, err := strconv.Atoi(account)
|
|
||||||
if err != nil || index < 0 {
|
|
||||||
return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warn("-------------------------------------------------------------------")
|
|
||||||
log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
|
|
||||||
log.Warn("This functionality is deprecated and will be removed in the future!")
|
|
||||||
log.Warn("Please use explicit addresses! (can search via `geth account list`)")
|
|
||||||
log.Warn("-------------------------------------------------------------------")
|
|
||||||
|
|
||||||
accs := ks.Accounts()
|
|
||||||
if len(accs) <= index {
|
|
||||||
return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
|
|
||||||
}
|
|
||||||
|
|
||||||
return accs[index], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setEtherbase retrieves the etherbase from the directly specified command line flags.
|
// setEtherbase retrieves the etherbase from the directly specified command line flags.
|
||||||
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
if ctx.IsSet(MinerEtherbaseFlag.Name) {
|
if ctx.IsSet(MinerEtherbaseFlag.Name) {
|
||||||
|
|
@ -1382,27 +1333,6 @@ func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
cfg.Miner.Etherbase = common.BytesToAddress(b)
|
cfg.Miner.Etherbase = common.BytesToAddress(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakePasswordList reads password lines from the file specified by the global --password flag.
|
|
||||||
func MakePasswordList(ctx *cli.Context) []string {
|
|
||||||
path := ctx.Path(PasswordFileFlag.Name)
|
|
||||||
if path == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
text, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
Fatalf("Failed to read password file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(text), "\n")
|
|
||||||
// Sanitise DOS line endings.
|
|
||||||
for i := range lines {
|
|
||||||
lines[i] = strings.TrimRight(lines[i], "\r")
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
setNodeKey(ctx, cfg)
|
setNodeKey(ctx, cfg)
|
||||||
setNAT(ctx, cfg)
|
setNAT(ctx, cfg)
|
||||||
|
|
@ -1461,9 +1391,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
||||||
if ctx.IsSet(JWTSecretFlag.Name) {
|
if ctx.IsSet(JWTSecretFlag.Name) {
|
||||||
cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
|
cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(EnablePersonal.Name) {
|
if ctx.IsSet(EnablePersonal.Name) {
|
||||||
cfg.EnablePersonal = true
|
log.Warn(fmt.Sprintf("Option --%s is deprecated. The 'personal' RPC namespace has been removed.", EnablePersonal.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(ExternalSignerFlag.Name) {
|
if ctx.IsSet(ExternalSignerFlag.Name) {
|
||||||
|
|
@ -1491,7 +1420,7 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(InsecureUnlockAllowedFlag.Name) {
|
if ctx.IsSet(InsecureUnlockAllowedFlag.Name) {
|
||||||
cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name)
|
log.Warn(fmt.Sprintf("Option %q is deprecated and has no effect", InsecureUnlockAllowedFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(DBEngineFlag.Name) {
|
if ctx.IsSet(DBEngineFlag.Name) {
|
||||||
|
|
@ -1771,7 +1700,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
if ctx.IsSet(SyncTargetFlag.Name) {
|
if ctx.IsSet(SyncTargetFlag.Name) {
|
||||||
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
|
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
|
||||||
} else if ctx.IsSet(SyncModeFlag.Name) {
|
} else if ctx.IsSet(SyncModeFlag.Name) {
|
||||||
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
|
if err = cfg.SyncMode.UnmarshalText([]byte(ctx.String(SyncModeFlag.Name))); err != nil {
|
||||||
|
Fatalf("invalid --syncmode flag: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(NetworkIdFlag.Name) {
|
if ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
|
|
@ -1862,11 +1793,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
cfg.SnapshotCache = 0 // Disabled
|
cfg.SnapshotCache = 0 // Disabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(DocRootFlag.Name) {
|
|
||||||
cfg.DocRoot = ctx.String(DocRootFlag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsSet(VMEnableDebugFlag.Name) {
|
if ctx.IsSet(VMEnableDebugFlag.Name) {
|
||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||||
|
|
@ -1928,14 +1854,15 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
passphrase string
|
passphrase string
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
if path := ctx.Path(PasswordFileFlag.Name); path != "" {
|
||||||
if list := MakePasswordList(ctx); len(list) > 0 {
|
if text, err := os.ReadFile(path); err != nil {
|
||||||
// Just take the first value. Although the function returns a possible multiple values and
|
Fatalf("Failed to read password file: %v", err)
|
||||||
// some usages iterate through them as attempts, that doesn't make sense in this setting,
|
} else {
|
||||||
// when we're definitely concerned with only one account.
|
if lines := strings.Split(string(text), "\n"); len(lines) > 0 {
|
||||||
passphrase = list[0]
|
passphrase = strings.TrimRight(lines[0], "\r") // Sanitise DOS line endings.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock the developer account by local keystore.
|
// Unlock the developer account by local keystore.
|
||||||
var ks *keystore.KeyStore
|
var ks *keystore.KeyStore
|
||||||
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
|
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
|
||||||
|
|
@ -1980,9 +1907,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not read genesis from database: %v", err)
|
Fatalf("Could not read genesis from database: %v", err)
|
||||||
}
|
}
|
||||||
if !genesis.Config.TerminalTotalDifficultyPassed {
|
|
||||||
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true")
|
|
||||||
}
|
|
||||||
if genesis.Config.TerminalTotalDifficulty == nil {
|
if genesis.Config.TerminalTotalDifficulty == nil {
|
||||||
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified")
|
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified")
|
||||||
} else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 {
|
} else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 {
|
||||||
|
|
@ -2016,17 +1940,87 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// VM tracing config.
|
// VM tracing config.
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
var config string
|
|
||||||
if ctx.IsSet(VMTraceJsonConfigFlag.Name) {
|
|
||||||
config = ctx.String(VMTraceJsonConfigFlag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.VMTrace = name
|
cfg.VMTrace = name
|
||||||
cfg.VMTraceJsonConfig = config
|
cfg.VMTraceJsonConfig = ctx.String(VMTraceJsonConfigFlag.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeBeaconLightConfig constructs a beacon light client config based on the
|
||||||
|
// related command line flags.
|
||||||
|
func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
|
||||||
|
var config bparams.ClientConfig
|
||||||
|
customConfig := ctx.IsSet(BeaconConfigFlag.Name)
|
||||||
|
CheckExclusive(ctx, MainnetFlag, SepoliaFlag, HoleskyFlag, BeaconConfigFlag)
|
||||||
|
switch {
|
||||||
|
case ctx.Bool(MainnetFlag.Name):
|
||||||
|
config.ChainConfig = *bparams.MainnetLightConfig
|
||||||
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
|
config.ChainConfig = *bparams.SepoliaLightConfig
|
||||||
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
|
config.ChainConfig = *bparams.HoleskyLightConfig
|
||||||
|
default:
|
||||||
|
if !customConfig {
|
||||||
|
config.ChainConfig = *bparams.MainnetLightConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Genesis root and time should always be specified together with custom chain config
|
||||||
|
if customConfig {
|
||||||
|
if !ctx.IsSet(BeaconGenesisRootFlag.Name) {
|
||||||
|
Fatalf("Custom beacon chain config is specified but genesis root is missing")
|
||||||
|
}
|
||||||
|
if !ctx.IsSet(BeaconGenesisTimeFlag.Name) {
|
||||||
|
Fatalf("Custom beacon chain config is specified but genesis time is missing")
|
||||||
|
}
|
||||||
|
if !ctx.IsSet(BeaconCheckpointFlag.Name) {
|
||||||
|
Fatalf("Custom beacon chain config is specified but checkpoint is missing")
|
||||||
|
}
|
||||||
|
config.ChainConfig = bparams.ChainConfig{
|
||||||
|
GenesisTime: ctx.Uint64(BeaconGenesisTimeFlag.Name),
|
||||||
|
}
|
||||||
|
if c, err := hexutil.Decode(ctx.String(BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 {
|
||||||
|
copy(config.GenesisValidatorsRoot[:len(c)], c)
|
||||||
|
} else {
|
||||||
|
Fatalf("Invalid hex string", "beacon.genesis.gvroot", ctx.String(BeaconGenesisRootFlag.Name), "error", err)
|
||||||
|
}
|
||||||
|
configFile := ctx.String(BeaconConfigFlag.Name)
|
||||||
|
if err := config.ChainConfig.LoadForks(configFile); err != nil {
|
||||||
|
Fatalf("Could not load beacon chain config", "file", configFile, "error", err)
|
||||||
|
}
|
||||||
|
log.Info("Using custom beacon chain config", "file", configFile)
|
||||||
|
} else {
|
||||||
|
if ctx.IsSet(BeaconGenesisRootFlag.Name) {
|
||||||
|
Fatalf("Genesis root is specified but custom beacon chain config is missing")
|
||||||
|
}
|
||||||
|
if ctx.IsSet(BeaconGenesisTimeFlag.Name) {
|
||||||
|
Fatalf("Genesis time is specified but custom beacon chain config is missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Checkpoint is required with custom chain config and is optional with pre-defined config
|
||||||
|
if ctx.IsSet(BeaconCheckpointFlag.Name) {
|
||||||
|
if c, err := hexutil.Decode(ctx.String(BeaconCheckpointFlag.Name)); err == nil && len(c) <= 32 {
|
||||||
|
copy(config.Checkpoint[:len(c)], c)
|
||||||
|
} else {
|
||||||
|
Fatalf("Invalid hex string", "beacon.checkpoint", ctx.String(BeaconCheckpointFlag.Name), "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.Apis = ctx.StringSlice(BeaconApiFlag.Name)
|
||||||
|
if config.Apis == nil {
|
||||||
|
Fatalf("Beacon node light client API URL not specified")
|
||||||
|
}
|
||||||
|
config.CustomHeader = make(map[string]string)
|
||||||
|
for _, s := range ctx.StringSlice(BeaconApiHeaderFlag.Name) {
|
||||||
|
kv := strings.Split(s, ":")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
Fatalf("Invalid custom API header entry: %s", s)
|
||||||
|
}
|
||||||
|
config.CustomHeader[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
|
||||||
|
}
|
||||||
|
config.Threshold = ctx.Int(BeaconThresholdFlag.Name)
|
||||||
|
config.NoFilter = ctx.Bool(BeaconNoFilterFlag.Name)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
// SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
|
// SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
|
||||||
// no URLs are set.
|
// no URLs are set.
|
||||||
func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
||||||
|
|
@ -2339,10 +2333,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
}
|
}
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
var config json.RawMessage
|
config := json.RawMessage(ctx.String(VMTraceJsonConfigFlag.Name))
|
||||||
if ctx.IsSet(VMTraceJsonConfigFlag.Name) {
|
|
||||||
config = json.RawMessage(ctx.String(VMTraceJsonConfigFlag.Name))
|
|
||||||
}
|
|
||||||
t, err := tracers.LiveDirectory.New(name, config)
|
t, err := tracers.LiveDirectory.New(name, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Failed to create tracer %q: %v", name, err)
|
Fatalf("Failed to create tracer %q: %v", name, err)
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,23 @@ var (
|
||||||
Usage: "Enable expensive metrics collection and reporting (deprecated)",
|
Usage: "Enable expensive metrics collection and reporting (deprecated)",
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
|
// Deprecated Oct 2024
|
||||||
|
EnablePersonal = &cli.BoolFlag{
|
||||||
|
Name: "rpc.enabledeprecatedpersonal",
|
||||||
|
Usage: "This used to enable the 'personal' namespace.",
|
||||||
|
Category: flags.DeprecatedCategory,
|
||||||
|
}
|
||||||
|
UnlockedAccountFlag = &cli.StringFlag{
|
||||||
|
Name: "unlock",
|
||||||
|
Usage: "Comma separated list of accounts to unlock (deprecated)",
|
||||||
|
Value: "",
|
||||||
|
Category: flags.DeprecatedCategory,
|
||||||
|
}
|
||||||
|
InsecureUnlockAllowedFlag = &cli.BoolFlag{
|
||||||
|
Name: "allow-insecure-unlock",
|
||||||
|
Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http (deprecated)",
|
||||||
|
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.
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ func Test_SplitTagsFlag(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) {
|
if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
|
|
||||||
|
|
@ -49,20 +49,3 @@ func GetPassPhrase(text string, confirmation bool) string {
|
||||||
|
|
||||||
return password
|
return password
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPassPhraseWithList retrieves the password associated with an account, either fetched
|
|
||||||
// from a list of preloaded passphrases, or requested interactively from the user.
|
|
||||||
func GetPassPhraseWithList(text string, confirmation bool, index int, passwords []string) string {
|
|
||||||
// If a list of passwords was supplied, retrieve from them
|
|
||||||
if len(passwords) > 0 {
|
|
||||||
if index < len(passwords) {
|
|
||||||
return passwords[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
return passwords[len(passwords)-1]
|
|
||||||
}
|
|
||||||
// Otherwise prompt the user for the password
|
|
||||||
password := GetPassPhrase(text, confirmation)
|
|
||||||
|
|
||||||
return password
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
// Copyright 2020 The go-ethereum Authors
|
|
||||||
// This file is part of go-ethereum.
|
|
||||||
//
|
|
||||||
// go-ethereum is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// go-ethereum is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Package utils contains internal helper functions for go-ethereum commands.
|
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetPassPhraseWithList(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
type args struct {
|
|
||||||
text string
|
|
||||||
confirmation bool
|
|
||||||
index int
|
|
||||||
passwords []string
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"test1",
|
|
||||||
args{
|
|
||||||
"text1",
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
[]string{"zero", "one", "two"},
|
|
||||||
},
|
|
||||||
"zero",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"test2",
|
|
||||||
args{
|
|
||||||
"text2",
|
|
||||||
false,
|
|
||||||
5,
|
|
||||||
[]string{"zero", "one", "two"},
|
|
||||||
},
|
|
||||||
"two",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"test3",
|
|
||||||
args{
|
|
||||||
"text3",
|
|
||||||
true,
|
|
||||||
1,
|
|
||||||
[]string{"zero", "one", "two"},
|
|
||||||
},
|
|
||||||
"one",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
if got := GetPassPhraseWithList(tt.args.text, tt.args.confirmation, tt.args.index, tt.args.passwords); got != tt.want {
|
|
||||||
t.Errorf("GetPassPhraseWithList() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -20,18 +20,13 @@ package math
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Various big integer limit values.
|
// Various big integer limit values.
|
||||||
var (
|
var (
|
||||||
tt255 = BigPow(2, 255)
|
|
||||||
tt256 = BigPow(2, 256)
|
tt256 = BigPow(2, 256)
|
||||||
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
|
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
|
||||||
tt63 = BigPow(2, 63)
|
|
||||||
MaxBig256 = new(big.Int).Set(tt256m1)
|
MaxBig256 = new(big.Int).Set(tt256m1)
|
||||||
MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -163,56 +158,6 @@ func BigPow(a, b int64) *big.Int {
|
||||||
return r.Exp(r, big.NewInt(b), nil)
|
return r.Exp(r, big.NewInt(b), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BigMax returns the larger of x or y.
|
|
||||||
func BigMax(x, y *big.Int) *big.Int {
|
|
||||||
if x.Cmp(y) < 0 {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigMaxUint(x, y *uint256.Int) *uint256.Int {
|
|
||||||
if x.Lt(y) {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// BigMin returns the smaller of x or y.
|
|
||||||
func BigMin(x, y *big.Int) *big.Int {
|
|
||||||
if x.Cmp(y) > 0 {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigMinUint256(x, y *uint256.Int) *uint256.Int {
|
|
||||||
if x.Gt(y) {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: @anshalshukla - check implementation correctness
|
|
||||||
func BigIntToUint256Int(x *big.Int) *uint256.Int {
|
|
||||||
return new(uint256.Int).SetBytes(x.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// FirstBitSet returns the index of the first 1 bit in v, counting from LSB.
|
|
||||||
func FirstBitSet(v *big.Int) int {
|
|
||||||
for i := 0; i < v.BitLen(); i++ {
|
|
||||||
if v.Bit(i) > 0 {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.BitLen()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length
|
// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length
|
||||||
// of the slice is at least n bytes.
|
// of the slice is at least n bytes.
|
||||||
func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
||||||
|
|
@ -226,36 +171,6 @@ func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// bigEndianByteAt returns the byte at position n,
|
|
||||||
// in Big-Endian encoding
|
|
||||||
// So n==0 returns the least significant byte
|
|
||||||
func bigEndianByteAt(bigint *big.Int, n int) byte {
|
|
||||||
words := bigint.Bits()
|
|
||||||
// Check word-bucket the byte will reside in
|
|
||||||
i := n / wordBytes
|
|
||||||
if i >= len(words) {
|
|
||||||
return byte(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
word := words[i]
|
|
||||||
// Offset of the byte
|
|
||||||
shift := 8 * uint(n%wordBytes)
|
|
||||||
|
|
||||||
return byte(word >> shift)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Byte returns the byte at position n,
|
|
||||||
// with the supplied padlength in Little-Endian encoding.
|
|
||||||
// n==0 returns the MSB
|
|
||||||
// Example: bigint '5', padlength 32, n=31 => 5
|
|
||||||
func Byte(bigint *big.Int, padlength, n int) byte {
|
|
||||||
if n >= padlength {
|
|
||||||
return byte(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bigEndianByteAt(bigint, padlength-1-n)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
|
// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
|
||||||
// that buf has enough space. If buf is too short the result will be incomplete.
|
// that buf has enough space. If buf is too short the result will be incomplete.
|
||||||
func ReadBits(bigint *big.Int, buf []byte) {
|
func ReadBits(bigint *big.Int, buf []byte) {
|
||||||
|
|
@ -279,40 +194,3 @@ func U256(x *big.Int) *big.Int {
|
||||||
func U256Bytes(n *big.Int) []byte {
|
func U256Bytes(n *big.Int) []byte {
|
||||||
return PaddedBigBytes(U256(n), 32)
|
return PaddedBigBytes(U256(n), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// S256 interprets x as a two's complement number.
|
|
||||||
// x must not exceed 256 bits (the result is undefined if it does) and is not modified.
|
|
||||||
//
|
|
||||||
// S256(0) = 0
|
|
||||||
// S256(1) = 1
|
|
||||||
// S256(2**255) = -2**255
|
|
||||||
// S256(2**256-1) = -1
|
|
||||||
func S256(x *big.Int) *big.Int {
|
|
||||||
if x.Cmp(tt255) < 0 {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
return new(big.Int).Sub(x, tt256)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exp implements exponentiation by squaring.
|
|
||||||
// Exp returns a newly-allocated big integer and does not change
|
|
||||||
// base or exponent. The result is truncated to 256 bits.
|
|
||||||
//
|
|
||||||
// Courtesy @karalabe and @chfast
|
|
||||||
func Exp(base, exponent *big.Int) *big.Int {
|
|
||||||
copyBase := new(big.Int).Set(base)
|
|
||||||
result := big.NewInt(1)
|
|
||||||
|
|
||||||
for _, word := range exponent.Bits() {
|
|
||||||
for i := 0; i < wordBits; i++ {
|
|
||||||
if word&1 == 1 {
|
|
||||||
U256(result.Mul(result, copyBase))
|
|
||||||
}
|
|
||||||
U256(copyBase.Mul(copyBase, copyBase))
|
|
||||||
word >>= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHexOrDecimal256(t *testing.T) {
|
func TestHexOrDecimal256(t *testing.T) {
|
||||||
|
|
@ -72,53 +70,6 @@ func TestMustParseBig256(t *testing.T) {
|
||||||
MustParseBig256("ggg")
|
MustParseBig256("ggg")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBigMax(t *testing.T) {
|
|
||||||
a := big.NewInt(10)
|
|
||||||
b := big.NewInt(5)
|
|
||||||
|
|
||||||
max1 := BigMax(a, b)
|
|
||||||
if max1 != a {
|
|
||||||
t.Errorf("Expected %d got %d", a, max1)
|
|
||||||
}
|
|
||||||
|
|
||||||
max2 := BigMax(b, a)
|
|
||||||
if max2 != a {
|
|
||||||
t.Errorf("Expected %d got %d", a, max2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBigMin(t *testing.T) {
|
|
||||||
a := big.NewInt(10)
|
|
||||||
b := big.NewInt(5)
|
|
||||||
|
|
||||||
min1 := BigMin(a, b)
|
|
||||||
if min1 != b {
|
|
||||||
t.Errorf("Expected %d got %d", b, min1)
|
|
||||||
}
|
|
||||||
|
|
||||||
min2 := BigMin(b, a)
|
|
||||||
if min2 != b {
|
|
||||||
t.Errorf("Expected %d got %d", b, min2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFirstBigSet(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
num *big.Int
|
|
||||||
ix int
|
|
||||||
}{
|
|
||||||
{big.NewInt(0), 0},
|
|
||||||
{big.NewInt(1), 0},
|
|
||||||
{big.NewInt(2), 1},
|
|
||||||
{big.NewInt(0x100), 8},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
if ix := FirstBitSet(test.num); ix != test.ix {
|
|
||||||
t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPaddedBigBytes(t *testing.T) {
|
func TestPaddedBigBytes(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
num *big.Int
|
num *big.Int
|
||||||
|
|
@ -158,20 +109,6 @@ func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkByteAtBrandNew(b *testing.B) {
|
|
||||||
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
bigEndianByteAt(bigint, 15)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkByteAt(b *testing.B) {
|
|
||||||
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
bigEndianByteAt(bigint, 15)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkByteAtOld(b *testing.B) {
|
func BenchmarkByteAtOld(b *testing.B) {
|
||||||
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
|
@ -222,107 +159,3 @@ func TestU256Bytes(t *testing.T) {
|
||||||
t.Errorf("expected %x got %x", ubytes, unsigned)
|
t.Errorf("expected %x got %x", ubytes, unsigned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBigEndianByteAt(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
x string
|
|
||||||
y int
|
|
||||||
exp byte
|
|
||||||
}{
|
|
||||||
{"00", 0, 0x00},
|
|
||||||
{"01", 1, 0x00},
|
|
||||||
{"00", 1, 0x00},
|
|
||||||
{"01", 0, 0x01},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
|
|
||||||
|
|
||||||
actual := bigEndianByteAt(v, test.y)
|
|
||||||
if actual != test.exp {
|
|
||||||
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func TestLittleEndianByteAt(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
x string
|
|
||||||
y int
|
|
||||||
exp byte
|
|
||||||
}{
|
|
||||||
{"00", 0, 0x00},
|
|
||||||
{"01", 1, 0x00},
|
|
||||||
{"00", 1, 0x00},
|
|
||||||
{"01", 0, 0x00},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB},
|
|
||||||
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD},
|
|
||||||
{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00},
|
|
||||||
{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30},
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20},
|
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0},
|
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF},
|
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
|
|
||||||
|
|
||||||
actual := Byte(v, 32, test.y)
|
|
||||||
if actual != test.exp {
|
|
||||||
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestS256(t *testing.T) {
|
|
||||||
tests := []struct{ x, y *big.Int }{
|
|
||||||
{x: big.NewInt(0), y: big.NewInt(0)},
|
|
||||||
{x: big.NewInt(1), y: big.NewInt(1)},
|
|
||||||
{x: big.NewInt(2), y: big.NewInt(2)},
|
|
||||||
{
|
|
||||||
x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)),
|
|
||||||
y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: BigPow(2, 255),
|
|
||||||
y: new(big.Int).Neg(BigPow(2, 255)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)),
|
|
||||||
y: big.NewInt(-1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)),
|
|
||||||
y: big.NewInt(-2),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
if y := S256(test.x); y.Cmp(test.y) != 0 {
|
|
||||||
t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExp(t *testing.T) {
|
|
||||||
tests := []struct{ base, exponent, result *big.Int }{
|
|
||||||
{base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)},
|
|
||||||
{base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)},
|
|
||||||
{base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)},
|
|
||||||
{base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)},
|
|
||||||
{base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")},
|
|
||||||
{base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 {
|
|
||||||
t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Integer limit values.
|
|
||||||
const (
|
|
||||||
MaxInt8 = 1<<7 - 1
|
|
||||||
MinInt8 = -1 << 7
|
|
||||||
MaxInt16 = 1<<15 - 1
|
|
||||||
MinInt16 = -1 << 15
|
|
||||||
MaxInt32 = 1<<31 - 1
|
|
||||||
MinInt32 = -1 << 31
|
|
||||||
MaxInt64 = 1<<63 - 1
|
|
||||||
MinInt64 = -1 << 63
|
|
||||||
MaxUint8 = 1<<8 - 1
|
|
||||||
MaxUint16 = 1<<16 - 1
|
|
||||||
MaxUint32 = 1<<32 - 1
|
|
||||||
MaxUint64 = 1<<64 - 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
||||||
type HexOrDecimal64 uint64
|
type HexOrDecimal64 uint64
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package math
|
package math
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,8 +37,8 @@ func TestOverflow(t *testing.T) {
|
||||||
op operation
|
op operation
|
||||||
}{
|
}{
|
||||||
// add operations
|
// add operations
|
||||||
{MaxUint64, 1, true, add},
|
{math.MaxUint64, 1, true, add},
|
||||||
{MaxUint64 - 1, 1, false, add},
|
{math.MaxUint64 - 1, 1, false, add},
|
||||||
|
|
||||||
// sub operations
|
// sub operations
|
||||||
{0, 1, true, sub},
|
{0, 1, true, sub},
|
||||||
|
|
@ -46,8 +47,8 @@ func TestOverflow(t *testing.T) {
|
||||||
// mul operations
|
// mul operations
|
||||||
{0, 0, false, mul},
|
{0, 0, false, mul},
|
||||||
{10, 10, false, mul},
|
{10, 10, false, mul},
|
||||||
{MaxUint64, 2, true, mul},
|
{math.MaxUint64, 2, true, mul},
|
||||||
{MaxUint64, 1, false, mul},
|
{math.MaxUint64, 1, false, mul},
|
||||||
} {
|
} {
|
||||||
var overflows bool
|
var overflows bool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ func FileExist(filePath string) bool {
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -115,9 +116,6 @@ func errOut(n int, err error) chan error {
|
||||||
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
|
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
|
||||||
// TTD is not defined yet, all headers should be in legacy format.
|
// TTD is not defined yet, all headers should be in legacy format.
|
||||||
ttd := chain.Config().TerminalTotalDifficulty
|
ttd := chain.Config().TerminalTotalDifficulty
|
||||||
if ttd == nil {
|
|
||||||
return headers, nil, nil
|
|
||||||
}
|
|
||||||
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
||||||
if ptd == nil {
|
if ptd == nil {
|
||||||
return nil, nil, consensus.ErrUnknownAncestor
|
return nil, nil, consensus.ErrUnknownAncestor
|
||||||
|
|
@ -349,7 +347,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize implements consensus.Engine and processes withdrawals on top.
|
// Finalize implements consensus.Engine and processes withdrawals on top.
|
||||||
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
||||||
if !beacon.IsPoSHeader(header) {
|
if !beacon.IsPoSHeader(header) {
|
||||||
beacon.ethone.Finalize(chain, header, state, body)
|
beacon.ethone.Finalize(chain, header, state, body)
|
||||||
return
|
return
|
||||||
|
|
@ -401,21 +399,25 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
|
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
preTrie, err := state.Database().OpenTrie(parent.Root)
|
preTrie, err := state.Database().OpenTrie(parent.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
|
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
|
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
|
||||||
vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
|
vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
|
||||||
|
|
||||||
|
// The witness is only attached iff both parent and current block are
|
||||||
|
// using verkle tree.
|
||||||
if okpre && okpost {
|
if okpre && okpost {
|
||||||
if len(keys) > 0 {
|
if len(keys) > 0 {
|
||||||
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys, vktPreTrie.FlatdbNodeResolver)
|
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
|
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
|
||||||
}
|
}
|
||||||
block = block.WithWitness(&types.ExecutionWitness{StateDiff: stateDiff, VerkleProof: verkleProof})
|
block = block.WithWitness(&types.ExecutionWitness{
|
||||||
|
StateDiff: stateDiff,
|
||||||
|
VerkleProof: verkleProof,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -495,9 +497,6 @@ func (beacon *Beacon) SetThreads(threads int) {
|
||||||
// It depends on the parentHash already being stored in the database.
|
// It depends on the parentHash already being stored in the database.
|
||||||
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
|
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
|
||||||
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
|
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
|
||||||
if chain.Config().TerminalTotalDifficulty == nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
td := chain.GetTd(parentHash, parentNumber)
|
td := chain.GetTd(parentHash, parentNumber)
|
||||||
if td == nil {
|
if td == nil {
|
||||||
return false, consensus.ErrUnknownAncestor
|
return false, consensus.ErrUnknownAncestor
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"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/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
|
|
@ -36,6 +35,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
@ -50,8 +50,6 @@ const (
|
||||||
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
|
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
|
||||||
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
|
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
|
||||||
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
||||||
|
|
||||||
wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Clique proof-of-authority protocol constants.
|
// Clique proof-of-authority protocol constants.
|
||||||
|
|
@ -140,9 +138,6 @@ var (
|
||||||
errRecentlySigned = errors.New("recently signed")
|
errRecentlySigned = errors.New("recently signed")
|
||||||
)
|
)
|
||||||
|
|
||||||
// SignerFn hashes and signs the data to be signed by a backing account.
|
|
||||||
type SignerFn func(signer accounts.Account, mimeType string, message []byte) ([]byte, error)
|
|
||||||
|
|
||||||
// ecrecover extracts the Ethereum account address from a signed header.
|
// ecrecover extracts the Ethereum account address from a signed header.
|
||||||
func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
|
func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
|
||||||
// If the signature's already cached, return that
|
// If the signature's already cached, return that
|
||||||
|
|
@ -184,7 +179,6 @@ type Clique struct {
|
||||||
proposals map[common.Address]bool // Current list of proposals we are pushing
|
proposals map[common.Address]bool // Current list of proposals we are pushing
|
||||||
|
|
||||||
signer common.Address // Ethereum address of the signing key
|
signer common.Address // Ethereum address of the signing key
|
||||||
signFn SignerFn // Signer function to authorize hashes with
|
|
||||||
lock sync.RWMutex // Protects the signer and proposals fields
|
lock sync.RWMutex // Protects the signer and proposals fields
|
||||||
|
|
||||||
// The fields below are for testing only
|
// The fields below are for testing only
|
||||||
|
|
@ -619,7 +613,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
|
||||||
|
|
||||||
// Finalize implements consensus.Engine. There is no post-transaction
|
// Finalize implements consensus.Engine. There is no post-transaction
|
||||||
// consensus rules in clique, do nothing here.
|
// consensus rules in clique, do nothing here.
|
||||||
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
||||||
// No block rewards in PoA, so the state remains as is
|
// No block rewards in PoA, so the state remains as is
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -641,17 +635,17 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
||||||
|
|
||||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||||
// with.
|
// with.
|
||||||
func (c *Clique) Authorize(signer common.Address, signFn SignerFn) {
|
func (c *Clique) Authorize(signer common.Address) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
c.signer = signer
|
c.signer = signer
|
||||||
c.signFn = signFn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seal implements consensus.Engine, attempting to create a sealed block using
|
// Seal implements consensus.Engine, attempting to create a sealed block using
|
||||||
// the local signing credentials.
|
// the local signing credentials.
|
||||||
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
||||||
|
// (PoS): Geth doesn't support sealing on clique but we'll keep it for running bor in dev mode.
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
|
|
||||||
// Sealing the genesis block is not supported
|
// Sealing the genesis block is not supported
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -88,7 +89,7 @@ type Engine interface {
|
||||||
//
|
//
|
||||||
// Note: The state database might be updated to reflect any consensus rules
|
// Note: The state database might be updated to reflect any consensus rules
|
||||||
// that happen at finalization (e.g. block rewards).
|
// that happen at finalization (e.g. block rewards).
|
||||||
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body)
|
Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body)
|
||||||
|
|
||||||
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
|
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
|
||||||
// rewards or process withdrawals) and assembles the final block.
|
// rewards or process withdrawals) and assembles the final block.
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,13 @@ import (
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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/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"
|
||||||
|
|
@ -481,7 +481,9 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
|
||||||
expDiff := periodCount.Sub(periodCount, big2)
|
expDiff := periodCount.Sub(periodCount, big2)
|
||||||
expDiff.Exp(big2, expDiff, nil)
|
expDiff.Exp(big2, expDiff, nil)
|
||||||
diff.Add(diff, expDiff)
|
diff.Add(diff, expDiff)
|
||||||
diff = math.BigMax(diff, params.MinimumDifficulty)
|
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
||||||
|
diff = params.MinimumDifficulty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +505,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
|
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
|
||||||
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
||||||
// Accumulate any block and uncle rewards
|
// Accumulate any block and uncle rewards
|
||||||
accumulateRewards(chain.Config(), state, header, body.Uncles)
|
accumulateRewards(chain.Config(), state, header, body.Uncles)
|
||||||
}
|
}
|
||||||
|
|
@ -566,7 +568,7 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
|
||||||
// accumulateRewards credits the coinbase of the given block with the mining
|
// accumulateRewards credits the coinbase of the given block with the mining
|
||||||
// reward. The total reward consists of the static block reward and rewards for
|
// reward. The total reward consists of the static block reward and rewards for
|
||||||
// included uncles. The coinbase of each uncle block is also rewarded.
|
// included uncles. The coinbase of each uncle block is also rewarded.
|
||||||
func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) {
|
func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) {
|
||||||
// Select the correct block reward based on chain progression
|
// Select the correct block reward based on chain progression
|
||||||
blockReward := FrontierBlockReward
|
blockReward := FrontierBlockReward
|
||||||
if config.IsByzantium(header.Number) {
|
if config.IsByzantium(header.Number) {
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -74,7 +73,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
|
||||||
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
||||||
// rules, transferring all balances of a set of DAO accounts to a single refund
|
// rules, transferring all balances of a set of DAO accounts to a single refund
|
||||||
// contract.
|
// contract.
|
||||||
func ApplyDAOHardFork(statedb *state.StateDB) {
|
func ApplyDAOHardFork(statedb vm.StateDB) {
|
||||||
// Retrieve the contract to refund balances into
|
// Retrieve the contract to refund balances into
|
||||||
if !statedb.Exist(params.DAORefundContract) {
|
if !statedb.Exist(params.DAORefundContract) {
|
||||||
statedb.CreateAccount(params.DAORefundContract)
|
statedb.CreateAccount(params.DAORefundContract)
|
||||||
|
|
@ -82,7 +81,8 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
|
||||||
|
|
||||||
// Move every DAO account and extra-balance account funds into the refund contract
|
// Move every DAO account and extra-balance account funds into the refund contract
|
||||||
for _, addr := range params.DAODrainList() {
|
for _, addr := range params.DAODrainList() {
|
||||||
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract)
|
balance := statedb.GetBalance(addr)
|
||||||
statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount)
|
statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
|
||||||
|
statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -82,19 +81,23 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(baseFeeChangeDenominatorUint64))
|
num.Div(num, denom.SetUint64(baseFeeChangeDenominatorUint64))
|
||||||
baseFeeDelta := math.BigMax(num, common.Big1)
|
if num.Cmp(common.Big1) < 0 {
|
||||||
|
return num.Add(parent.BaseFee, common.Big1)
|
||||||
return num.Add(parent.BaseFee, baseFeeDelta)
|
}
|
||||||
|
return num.Add(parent.BaseFee, num)
|
||||||
} else {
|
} else {
|
||||||
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
|
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
|
||||||
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
||||||
num.SetUint64(parentGasTarget - parent.GasUsed)
|
num.SetUint64(parentGasTarget - parent.GasUsed)
|
||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(baseFeeChangeDenominatorUint64))
|
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
||||||
baseFee := num.Sub(parent.BaseFee, num)
|
|
||||||
|
|
||||||
return math.BigMax(baseFee, common.Big0)
|
baseFee := num.Sub(parent.BaseFee, num)
|
||||||
|
if baseFee.Cmp(common.Big0) < 0 {
|
||||||
|
baseFee = common.Big0
|
||||||
|
}
|
||||||
|
return baseFee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,12 @@ package console
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/console/prompt"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
|
|
@ -51,302 +48,6 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getJeth(vm *goja.Runtime) *goja.Object {
|
|
||||||
jeth := vm.Get("jeth")
|
|
||||||
if jeth == nil {
|
|
||||||
panic(vm.ToValue("jeth object does not exist"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return jeth.ToObject(vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAccount is a wrapper around the personal.newAccount RPC method that uses a
|
|
||||||
// non-echoing password prompt to acquire the passphrase and executes the original
|
|
||||||
// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
|
|
||||||
func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) {
|
|
||||||
var (
|
|
||||||
password string
|
|
||||||
confirm string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
// No password was specified, prompt the user for it
|
|
||||||
case len(call.Arguments) == 0:
|
|
||||||
if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if password != confirm {
|
|
||||||
return nil, errors.New("passwords don't match")
|
|
||||||
}
|
|
||||||
// A single string password was specified, use that
|
|
||||||
case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil:
|
|
||||||
password = call.Argument(0).ToString().String()
|
|
||||||
default:
|
|
||||||
return nil, errors.New("expected 0 or 1 string argument")
|
|
||||||
}
|
|
||||||
// Password acquired, execute the call and return
|
|
||||||
newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.newAccount is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, err := newAccount(goja.Null(), call.VM.ToValue(password))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenWallet is a wrapper around personal.openWallet which can interpret and
|
|
||||||
// react to certain error messages, such as the Trezor PIN matrix request.
|
|
||||||
func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) {
|
|
||||||
// Make sure we have a wallet specified to open
|
|
||||||
if call.Argument(0).ToObject(call.VM).ClassName() != "String" {
|
|
||||||
return nil, errors.New("first argument must be the wallet URL to open")
|
|
||||||
}
|
|
||||||
|
|
||||||
wallet := call.Argument(0)
|
|
||||||
|
|
||||||
var passwd goja.Value
|
|
||||||
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
|
|
||||||
passwd = call.VM.ToValue("")
|
|
||||||
} else {
|
|
||||||
passwd = call.Argument(1)
|
|
||||||
}
|
|
||||||
// Open the wallet and return if successful in itself
|
|
||||||
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.openWallet is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := openWallet(goja.Null(), wallet, passwd)
|
|
||||||
if err == nil {
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wallet open failed, report error unless it's a PIN or PUK entry
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()):
|
|
||||||
val, err = b.readPinAndReopenWallet(call)
|
|
||||||
if err == nil {
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err = b.readPassphraseAndReopenWallet(call)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()):
|
|
||||||
// PUK input requested, fetch from the user and call open again
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter the pairing password: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
passwd = call.VM.ToValue(input)
|
|
||||||
if val, err = openWallet(goja.Null(), wallet, passwd); err != nil {
|
|
||||||
if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// PIN input requested, fetch from the user and call open again
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()):
|
|
||||||
// PIN unblock requested, fetch PUK and new PIN from the user
|
|
||||||
var pukpin string
|
|
||||||
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter current PUK: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pukpin = input
|
|
||||||
|
|
||||||
input, err = b.prompter.PromptPassword("Please enter new PIN: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pukpin += input
|
|
||||||
|
|
||||||
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()):
|
|
||||||
// PIN input requested, fetch from the user and call open again
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Unknown error occurred, drop to the user
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) {
|
|
||||||
wallet := call.Argument(0)
|
|
||||||
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter your passphrase: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.openWallet is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) {
|
|
||||||
wallet := call.Argument(0)
|
|
||||||
// Trezor PIN matrix input requested, display the matrix to the user and fetch the data
|
|
||||||
fmt.Fprintf(b.printer, "Look at the device for number positions\n\n")
|
|
||||||
fmt.Fprintf(b.printer, "7 | 8 | 9\n")
|
|
||||||
fmt.Fprintf(b.printer, "--+---+--\n")
|
|
||||||
fmt.Fprintf(b.printer, "4 | 5 | 6\n")
|
|
||||||
fmt.Fprintf(b.printer, "--+---+--\n")
|
|
||||||
fmt.Fprintf(b.printer, "1 | 2 | 3\n\n")
|
|
||||||
|
|
||||||
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.openWallet is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
|
|
||||||
// uses a non-echoing password prompt to acquire the passphrase and executes the
|
|
||||||
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
|
|
||||||
// the RPC call.
|
|
||||||
func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
|
|
||||||
if len(call.Arguments) < 1 {
|
|
||||||
return nil, errors.New("usage: unlockAccount(account, [ password, duration ])")
|
|
||||||
}
|
|
||||||
|
|
||||||
account := call.Argument(0)
|
|
||||||
// Make sure we have an account specified to unlock.
|
|
||||||
if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String {
|
|
||||||
return nil, errors.New("first argument must be the account to unlock")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If password is not given or is the null value, prompt the user for it.
|
|
||||||
var passwd goja.Value
|
|
||||||
|
|
||||||
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
|
|
||||||
fmt.Fprintf(b.printer, "Unlock account %s\n", account)
|
|
||||||
|
|
||||||
input, err := b.prompter.PromptPassword("Passphrase: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
passwd = call.VM.ToValue(input)
|
|
||||||
} else {
|
|
||||||
if call.Argument(1).ExportType().Kind() != reflect.String {
|
|
||||||
return nil, errors.New("password must be a string")
|
|
||||||
}
|
|
||||||
|
|
||||||
passwd = call.Argument(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Third argument is the duration how long the account should be unlocked.
|
|
||||||
duration := goja.Null()
|
|
||||||
|
|
||||||
if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) {
|
|
||||||
if !isNumber(call.Argument(2)) {
|
|
||||||
return nil, errors.New("unlock duration must be a number")
|
|
||||||
}
|
|
||||||
|
|
||||||
duration = call.Argument(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the request to the backend and return.
|
|
||||||
unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.unlockAccount is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
return unlockAccount(goja.Null(), account, passwd, duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
|
|
||||||
// prompt to acquire the passphrase and executes the original RPC method (saved in
|
|
||||||
// jeth.sign) with it to actually execute the RPC call.
|
|
||||||
func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
|
|
||||||
if nArgs := len(call.Arguments); nArgs < 2 {
|
|
||||||
return nil, errors.New("usage: sign(message, account, [ password ])")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
message = call.Argument(0)
|
|
||||||
account = call.Argument(1)
|
|
||||||
passwd = call.Argument(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String {
|
|
||||||
return nil, errors.New("first argument must be the message to sign")
|
|
||||||
}
|
|
||||||
|
|
||||||
if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String {
|
|
||||||
return nil, errors.New("second argument must be the account to sign with")
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the password is not given or null ask the user and ensure password is a string
|
|
||||||
if goja.IsUndefined(passwd) || goja.IsNull(passwd) {
|
|
||||||
fmt.Fprintf(b.printer, "Give password for account %s\n", account)
|
|
||||||
|
|
||||||
input, err := b.prompter.PromptPassword("Password: ")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
passwd = call.VM.ToValue(input)
|
|
||||||
} else if passwd.ExportType().Kind() != reflect.String {
|
|
||||||
return nil, errors.New("third argument must be the password to unlock the account")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the request to the backend and return
|
|
||||||
sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign"))
|
|
||||||
if !callable {
|
|
||||||
return nil, errors.New("jeth.sign is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign(goja.Null(), message, account, passwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep will block the console for the specified number of seconds.
|
// Sleep will block the console for the specified number of seconds.
|
||||||
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
||||||
if nArgs := len(call.Arguments); nArgs < 1 {
|
if nArgs := len(call.Arguments); nArgs < 1 {
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,6 @@ func (c *Console) init(preload []string) error {
|
||||||
// Add bridge overrides for web3.js functionality.
|
// Add bridge overrides for web3.js functionality.
|
||||||
c.jsre.Do(func(vm *goja.Runtime) {
|
c.jsre.Do(func(vm *goja.Runtime) {
|
||||||
c.initAdmin(vm, bridge)
|
c.initAdmin(vm, bridge)
|
||||||
c.initPersonal(vm, bridge)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Preload JavaScript files.
|
// Preload JavaScript files.
|
||||||
|
|
@ -268,32 +267,6 @@ func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initPersonal redirects account-related API methods through the bridge.
|
|
||||||
//
|
|
||||||
// If the console is in interactive mode and the 'personal' API is available, override
|
|
||||||
// the openWallet, unlockAccount, newAccount and sign methods since these require user
|
|
||||||
// interaction. The original web3 callbacks are stored in 'jeth'. These will be called
|
|
||||||
// by the bridge after the prompt and send the original web3 request to the backend.
|
|
||||||
func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) {
|
|
||||||
personal := getObject(vm, "personal")
|
|
||||||
if personal == nil || c.prompter == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warn("Enabling deprecated personal namespace")
|
|
||||||
|
|
||||||
jeth := vm.NewObject()
|
|
||||||
vm.Set("jeth", jeth)
|
|
||||||
jeth.Set("openWallet", personal.Get("openWallet"))
|
|
||||||
jeth.Set("unlockAccount", personal.Get("unlockAccount"))
|
|
||||||
jeth.Set("newAccount", personal.Get("newAccount"))
|
|
||||||
jeth.Set("sign", personal.Get("sign"))
|
|
||||||
personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet))
|
|
||||||
personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount))
|
|
||||||
personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount))
|
|
||||||
personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Console) clearHistory() {
|
func (c *Console) clearHistory() {
|
||||||
c.history = nil
|
c.history = nil
|
||||||
c.prompter.ClearHistory()
|
c.prompter.ClearHistory()
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,13 @@ import (
|
||||||
|
|
||||||
// Iterator for disassembled EVM instructions
|
// Iterator for disassembled EVM instructions
|
||||||
type instructionIterator struct {
|
type instructionIterator struct {
|
||||||
code []byte
|
code []byte
|
||||||
pc uint64
|
pc uint64
|
||||||
arg []byte
|
arg []byte
|
||||||
op vm.OpCode
|
op vm.OpCode
|
||||||
error error
|
error error
|
||||||
started bool
|
started bool
|
||||||
|
eofEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInstructionIterator creates a new instruction iterator.
|
// NewInstructionIterator creates a new instruction iterator.
|
||||||
|
|
@ -42,6 +43,13 @@ func NewInstructionIterator(code []byte) *instructionIterator {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEOFInstructionIterator creates a new instruction iterator for EOF-code.
|
||||||
|
func NewEOFInstructionIterator(code []byte) *instructionIterator {
|
||||||
|
it := NewInstructionIterator(code)
|
||||||
|
it.eofEnabled = true
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
// Next returns true if there is a next instruction and moves on.
|
// Next returns true if there is a next instruction and moves on.
|
||||||
func (it *instructionIterator) Next() bool {
|
func (it *instructionIterator) Next() bool {
|
||||||
if it.error != nil || uint64(len(it.code)) <= it.pc {
|
if it.error != nil || uint64(len(it.code)) <= it.pc {
|
||||||
|
|
@ -65,13 +73,26 @@ func (it *instructionIterator) Next() bool {
|
||||||
// We reached the end.
|
// We reached the end.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
it.op = vm.OpCode(it.code[it.pc])
|
it.op = vm.OpCode(it.code[it.pc])
|
||||||
if it.op.IsPush() {
|
var a int
|
||||||
a := uint64(it.op) - uint64(vm.PUSH0)
|
if !it.eofEnabled { // Legacy code
|
||||||
u := it.pc + 1 + a
|
if it.op.IsPush() {
|
||||||
|
a = int(it.op) - int(vm.PUSH0)
|
||||||
|
}
|
||||||
|
} else { // EOF code
|
||||||
|
if it.op == vm.RJUMPV {
|
||||||
|
// RJUMPV is unique as it has a variable sized operand. The total size is
|
||||||
|
// determined by the count byte which immediately follows RJUMPV.
|
||||||
|
maxIndex := int(it.code[it.pc+1])
|
||||||
|
a = (maxIndex+1)*2 + 1
|
||||||
|
} else {
|
||||||
|
a = vm.Immediates(it.op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if a > 0 {
|
||||||
|
u := it.pc + 1 + uint64(a)
|
||||||
if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u {
|
if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u {
|
||||||
it.error = fmt.Errorf("incomplete push instruction at %v", it.pc)
|
it.error = fmt.Errorf("incomplete instruction at %v", it.pc)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +130,6 @@ func PrintDisassembled(code string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
it := NewInstructionIterator(script)
|
it := NewInstructionIterator(script)
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
if it.Arg() != nil && 0 < len(it.Arg()) {
|
if it.Arg() != nil && 0 < len(it.Arg()) {
|
||||||
|
|
|
||||||
|
|
@ -17,42 +17,78 @@
|
||||||
package asm
|
package asm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tests disassembling instructions
|
// Tests disassembling instructions
|
||||||
func TestInstructionIterator(t *testing.T) {
|
func TestInstructionIterator(t *testing.T) {
|
||||||
for i, tc := range []struct {
|
for i, tc := range []struct {
|
||||||
want int
|
code string
|
||||||
code string
|
legacyWant string
|
||||||
wantErr string
|
eofWant string
|
||||||
}{
|
}{
|
||||||
{2, "61000000", ""}, // valid code
|
{"", "", ""}, // empty
|
||||||
{0, "6100", "incomplete push instruction at 0"}, // invalid code
|
{"6100", `err: incomplete instruction at 0`, `err: incomplete instruction at 0`},
|
||||||
{2, "5900", ""}, // push0
|
{"61000000", `
|
||||||
{0, "", ""}, // empty
|
00000: PUSH2 0x0000
|
||||||
|
00003: STOP`, `
|
||||||
|
00000: PUSH2 0x0000
|
||||||
|
00003: STOP`},
|
||||||
|
{"5F00", `
|
||||||
|
00000: PUSH0
|
||||||
|
00001: STOP`, `
|
||||||
|
00000: PUSH0
|
||||||
|
00001: STOP`},
|
||||||
|
{"d1aabb00", `00000: DATALOADN
|
||||||
|
00001: opcode 0xaa not defined
|
||||||
|
00002: opcode 0xbb not defined
|
||||||
|
00003: STOP`, `
|
||||||
|
00000: DATALOADN 0xaabb
|
||||||
|
00003: STOP`}, // DATALOADN(aabb),STOP
|
||||||
|
{"d1aa", `
|
||||||
|
00000: DATALOADN
|
||||||
|
00001: opcode 0xaa not defined`, "err: incomplete instruction at 0\n"}, // DATALOADN(aa) invalid
|
||||||
|
{"e20211223344556600", `
|
||||||
|
00000: RJUMPV
|
||||||
|
00001: MUL
|
||||||
|
00002: GT
|
||||||
|
00003: opcode 0x22 not defined
|
||||||
|
00004: CALLER
|
||||||
|
00005: DIFFICULTY
|
||||||
|
00006: SSTORE
|
||||||
|
err: incomplete instruction at 7`, `
|
||||||
|
00000: RJUMPV 0x02112233445566
|
||||||
|
00008: STOP`}, // RJUMPV( 6 bytes), STOP
|
||||||
|
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
have int
|
|
||||||
code, _ = hex.DecodeString(tc.code)
|
code, _ = hex.DecodeString(tc.code)
|
||||||
it = NewInstructionIterator(code)
|
legacy = strings.TrimSpace(disassembly(NewInstructionIterator(code)))
|
||||||
|
eof = strings.TrimSpace(disassembly(NewEOFInstructionIterator(code)))
|
||||||
)
|
)
|
||||||
for it.Next() {
|
if want := strings.TrimSpace(tc.legacyWant); legacy != want {
|
||||||
have++
|
t.Errorf("test %d: wrong (legacy) output. have:\n%q\nwant:\n%q\n", i, legacy, want)
|
||||||
}
|
}
|
||||||
var haveErr = ""
|
if want := strings.TrimSpace(tc.eofWant); eof != want {
|
||||||
if it.Error() != nil {
|
t.Errorf("test %d: wrong (eof) output. have:\n%q\nwant:\n%q\n", i, eof, want)
|
||||||
haveErr = it.Error().Error()
|
|
||||||
}
|
|
||||||
if haveErr != tc.wantErr {
|
|
||||||
t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if have != tc.want {
|
|
||||||
t.Errorf("wrong instruction count, have %d want %d", have, tc.want)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func disassembly(it *instructionIterator) string {
|
||||||
|
var out = new(strings.Builder)
|
||||||
|
for it.Next() {
|
||||||
|
if it.Arg() != nil && 0 < len(it.Arg()) {
|
||||||
|
fmt.Fprintf(out, "%05x: %v %#x\n", it.PC(), it.Op(), it.Arg())
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(out, "%05x: %v\n", it.PC(), it.Op())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := it.Error(); err != nil {
|
||||||
|
fmt.Fprintf(out, "err: %v\n", err)
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"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/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -80,9 +81,15 @@ var (
|
||||||
// value-transfer transaction with n bytes of extra data in each
|
// value-transfer transaction with n bytes of extra data in each
|
||||||
// block.
|
// block.
|
||||||
func genValueTx(nbytes int) func(int, *BlockGen) {
|
func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||||
|
// We can reuse the data for all transactions.
|
||||||
|
// During signing, the method tx.WithSignature(s, sig)
|
||||||
|
// performs:
|
||||||
|
// cpy := tx.inner.copy()
|
||||||
|
// cpy.setSignatureValues(signer.ChainID(), v, r, s)
|
||||||
|
// After this operation, the data can be reused by the caller.
|
||||||
|
data := make([]byte, nbytes)
|
||||||
return func(i int, gen *BlockGen) {
|
return func(i int, gen *BlockGen) {
|
||||||
toaddr := common.Address{}
|
toaddr := common.Address{}
|
||||||
data := make([]byte, nbytes)
|
|
||||||
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
||||||
signer := gen.Signer()
|
signer := gen.Signer()
|
||||||
gasPrice := big.NewInt(0)
|
gasPrice := big.NewInt(0)
|
||||||
|
|
@ -182,22 +189,16 @@ func genUncles(i int, gen *BlockGen) {
|
||||||
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
// Create the database in memory or in a temporary directory.
|
// Create the database in memory or in a temporary directory.
|
||||||
var db ethdb.Database
|
var db ethdb.Database
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if !disk {
|
if !disk {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
} else {
|
} else {
|
||||||
dir := b.TempDir()
|
pdb, err := pebble.New(b.TempDir(), 128, 128, "", false)
|
||||||
|
|
||||||
db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "", false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("cannot create temporary database: %v", err)
|
b.Fatalf("cannot create temporary database: %v", err)
|
||||||
}
|
}
|
||||||
|
db = rawdb.NewDatabase(pdb)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a chain of b.N blocks using the supplied block
|
// Generate a chain of b.N blocks using the supplied block
|
||||||
// generator function.
|
// generator function.
|
||||||
gspec := &Genesis{
|
gspec := &Genesis{
|
||||||
|
|
@ -225,15 +226,27 @@ func BenchmarkChainRead_full_10k(b *testing.B) {
|
||||||
benchReadChain(b, true, 10000)
|
benchReadChain(b, true, 10000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainRead_header_100k(b *testing.B) {
|
func BenchmarkChainRead_header_100k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchReadChain(b, false, 100000)
|
benchReadChain(b, false, 100000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainRead_full_100k(b *testing.B) {
|
func BenchmarkChainRead_full_100k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchReadChain(b, true, 100000)
|
benchReadChain(b, true, 100000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainRead_header_500k(b *testing.B) {
|
func BenchmarkChainRead_header_500k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchReadChain(b, false, 500000)
|
benchReadChain(b, false, 500000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainRead_full_500k(b *testing.B) {
|
func BenchmarkChainRead_full_500k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchReadChain(b, true, 500000)
|
benchReadChain(b, true, 500000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainWrite_header_10k(b *testing.B) {
|
func BenchmarkChainWrite_header_10k(b *testing.B) {
|
||||||
|
|
@ -249,9 +262,15 @@ func BenchmarkChainWrite_full_100k(b *testing.B) {
|
||||||
benchWriteChain(b, true, 100000)
|
benchWriteChain(b, true, 100000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainWrite_header_500k(b *testing.B) {
|
func BenchmarkChainWrite_header_500k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchWriteChain(b, false, 500000)
|
benchWriteChain(b, false, 500000)
|
||||||
}
|
}
|
||||||
func BenchmarkChainWrite_full_500k(b *testing.B) {
|
func BenchmarkChainWrite_full_500k(b *testing.B) {
|
||||||
|
if testing.Short() {
|
||||||
|
b.Skip("Skipping in short-mode")
|
||||||
|
}
|
||||||
benchWriteChain(b, true, 500000)
|
benchWriteChain(b, true, 500000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,13 +315,11 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin
|
||||||
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
dir := b.TempDir()
|
pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false)
|
||||||
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
|
db := rawdb.NewDatabase(pdb)
|
||||||
makeChainForBench(db, genesis, full, count)
|
makeChainForBench(db, genesis, full, count)
|
||||||
db.Close()
|
db.Close()
|
||||||
}
|
}
|
||||||
|
|
@ -311,10 +328,11 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
|
||||||
func benchReadChain(b *testing.B, full bool, count uint64) {
|
func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
dir := b.TempDir()
|
dir := b.TempDir()
|
||||||
|
|
||||||
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
pdb, err := pebble.New(dir, 1024, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
|
db := rawdb.NewDatabase(pdb)
|
||||||
|
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
makeChainForBench(db, genesis, full, count)
|
makeChainForBench(db, genesis, full, count)
|
||||||
|
|
@ -327,15 +345,16 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
pdb, err = pebble.New(dir, 1024, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
db = rawdb.NewDatabase(pdb)
|
||||||
|
|
||||||
|
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for n := uint64(0); n < count; n++ {
|
for n := uint64(0); n < count; n++ {
|
||||||
header := chain.GetHeaderByNumber(n)
|
header := chain.GetHeaderByNumber(n)
|
||||||
if full {
|
if full {
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
// such as amount of used gas, the receipt roots and the state root itself.
|
// such as amount of used gas, the receipt roots and the state root itself.
|
||||||
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return fmt.Errorf("nil ProcessResult value")
|
return errors.New("nil ProcessResult value")
|
||||||
}
|
}
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if block.GasUsed() != res.GasUsed {
|
if block.GasUsed() != res.GasUsed {
|
||||||
|
|
@ -151,10 +151,12 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
||||||
}
|
}
|
||||||
// Validate the parsed requests match the expected header value.
|
// Validate the parsed requests match the expected header value.
|
||||||
if header.RequestsHash != nil {
|
if header.RequestsHash != nil {
|
||||||
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
|
reqhash := types.CalcRequestsHash(res.Requests)
|
||||||
if depositSha != *header.RequestsHash {
|
if reqhash != *header.RequestsHash {
|
||||||
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
|
return fmt.Errorf("invalid requests hash (remote: %x local: %x)", *header.RequestsHash, reqhash)
|
||||||
}
|
}
|
||||||
|
} else if res.Requests != nil {
|
||||||
|
return errors.New("block has requests before prague fork")
|
||||||
}
|
}
|
||||||
// Validate the state root against the received state root and throw
|
// Validate the state root against the received state root and throw
|
||||||
// an error if they don't match.
|
// an error if they don't match.
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||||
}
|
}
|
||||||
copy(gspec.ExtraData[32:], addr[:])
|
copy(gspec.ExtraData[32:], addr[:])
|
||||||
|
|
||||||
|
// chain_maker has no blockchain to retrieve the TTD from, setting to nil
|
||||||
|
// is a hack to signal it to generate pre-merge blocks
|
||||||
|
gspec.Config.TerminalTotalDifficulty = nil
|
||||||
td := 0
|
td := 0
|
||||||
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
|
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
|
||||||
|
|
||||||
|
|
@ -154,7 +157,6 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||||
|
|
||||||
preBlocks = blocks
|
preBlocks = blocks
|
||||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
|
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
|
||||||
t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty)
|
|
||||||
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
|
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,13 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -180,9 +178,9 @@ func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||||
}
|
}
|
||||||
if c.StateScheme == rawdb.PathScheme {
|
if c.StateScheme == rawdb.PathScheme {
|
||||||
config.PathDB = &pathdb.Config{
|
config.PathDB = &pathdb.Config{
|
||||||
StateHistory: c.StateHistory,
|
StateHistory: c.StateHistory,
|
||||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||||
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
|
|
@ -248,7 +246,6 @@ type BlockChain struct {
|
||||||
hc *HeaderChain
|
hc *HeaderChain
|
||||||
rmLogsFeed event.Feed
|
rmLogsFeed event.Feed
|
||||||
chainFeed event.Feed
|
chainFeed event.Feed
|
||||||
chainSideFeed event.Feed
|
|
||||||
chainHeadFeed event.Feed
|
chainHeadFeed event.Feed
|
||||||
logsFeed event.Feed
|
logsFeed event.Feed
|
||||||
blockProcFeed event.Feed
|
blockProcFeed event.Feed
|
||||||
|
|
@ -807,18 +804,14 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
}
|
}
|
||||||
// Send chain head event to update the transaction pool
|
// Send chain head event to update the transaction pool
|
||||||
header := bc.CurrentBlock()
|
header := bc.CurrentBlock()
|
||||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
if block := bc.GetBlock(header.Hash(), header.Number.Uint64()); block == nil {
|
||||||
|
|
||||||
if block == nil {
|
|
||||||
// This should never happen. In practice, previously 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())
|
||||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
|
bc.chainHeadFeed.Send(ChainHeadEvent{Header: header})
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -832,18 +825,14 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
|
||||||
}
|
}
|
||||||
// Send chain head event to update the transaction pool
|
// Send chain head event to update the transaction pool
|
||||||
header := bc.CurrentBlock()
|
header := bc.CurrentBlock()
|
||||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
if block := bc.GetBlock(header.Hash(), header.Number.Uint64()); block == nil {
|
||||||
|
|
||||||
if block == nil {
|
|
||||||
// This should never happen. In practice, previously 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())
|
||||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
|
bc.chainHeadFeed.Send(ChainHeadEvent{Header: header})
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1799,7 +1788,7 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
|
||||||
func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
||||||
current := bc.CurrentBlock()
|
current := bc.CurrentBlock()
|
||||||
if block.ParentHash() != current.Hash() {
|
if block.ParentHash() != current.Hash() {
|
||||||
if err := bc.reorg(current, block); err != nil {
|
if err := bc.reorg(current, block.Header()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1965,7 +1954,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||||
if reorg {
|
if reorg {
|
||||||
// Reorganise the chain if the parent is not the head block
|
// Reorganise the chain if the parent is not the head block
|
||||||
if block.ParentHash() != currentBlock.Hash() {
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
if err = bc.reorg(currentBlock, block); err != nil {
|
if err = bc.reorg(currentBlock, block.Header()); err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1978,26 +1967,23 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||||
// Set new head.
|
// Set new head.
|
||||||
if status == CanonStatTy {
|
if status == CanonStatTy {
|
||||||
bc.writeHeadBlock(block)
|
bc.writeHeadBlock(block)
|
||||||
}
|
|
||||||
if status == CanonStatTy {
|
bc.chainFeed.Send(ChainEvent{Header: block.Header()})
|
||||||
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
|
|
||||||
|
|
||||||
if len(logs) > 0 {
|
if len(logs) > 0 {
|
||||||
bc.logsFeed.Send(logs)
|
bc.logsFeed.Send(logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// send state sync logs into logs feed
|
// send state sync logs into logs feed
|
||||||
if len(stateSyncLogs) > 0 {
|
if len(stateSyncLogs) > 0 {
|
||||||
bc.logsFeed.Send(stateSyncLogs)
|
bc.logsFeed.Send(stateSyncLogs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// In theory, we should fire a ChainHeadEvent when we inject
|
// In theory, we should fire a ChainHeadEvent when we inject
|
||||||
// a canonical block, but sometimes we can insert a batch of
|
// a canonical block, but sometimes we can insert a batch of
|
||||||
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
||||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||||
// event here.
|
// event here.
|
||||||
if emitHeadEvent {
|
if emitHeadEvent {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Header: block.Header()})
|
||||||
// BOR state sync feed related changes
|
// BOR state sync feed related changes
|
||||||
for _, data := range bc.stateSyncData {
|
for _, data := range bc.stateSyncData {
|
||||||
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
|
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
|
||||||
|
|
@ -2102,7 +2088,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
||||||
// Fire a single chain head event if we've progressed the chain
|
// Fire a single chain head event if we've progressed the chain
|
||||||
defer func() {
|
defer func() {
|
||||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Header: lastCanon.Header()})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Start the parallel header verifier
|
// Start the parallel header verifier
|
||||||
|
|
@ -2334,6 +2320,27 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
}
|
}
|
||||||
|
statedb, err := state.New(parent.Root, bc.statedb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, it.index, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
||||||
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
|
if bc.chainConfig.IsByzantium(block.Number()) {
|
||||||
|
// Generate witnesses either if we're self-testing, or if it's the
|
||||||
|
// only block being inserted. A bit crude, but witnesses are huge,
|
||||||
|
// so we refuse to make an entire chain of them.
|
||||||
|
if bc.vmConfig.StatelessSelfValidation || (makeWitness && len(chain) == 1) {
|
||||||
|
witness, err = stateless.NewWitness(block.Header(), bc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, it.index, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statedb.StartPrefetcher("chain", witness)
|
||||||
|
}
|
||||||
|
activeState = statedb
|
||||||
|
|
||||||
// If we have a followup block, run that against the current state to pre-cache
|
// If we have a followup block, run that against the current state to pre-cache
|
||||||
// transactions and probabilistically some of the account/storage trie nodes.
|
// transactions and probabilistically some of the account/storage trie nodes.
|
||||||
|
|
@ -2846,8 +2853,8 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
|
||||||
return block.Hash(), nil
|
return block.Hash(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectLogs collects the logs that were generated or removed during
|
// collectLogs collects the logs that were generated or removed during the
|
||||||
// the processing of a block. These logs are later announced as deleted or reborn.
|
// processing of a block. These logs are later announced as deleted or reborn.
|
||||||
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
excessBlobGas := b.ExcessBlobGas()
|
excessBlobGas := b.ExcessBlobGas()
|
||||||
|
|
@ -2882,80 +2889,55 @@ func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||||
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
||||||
// blocks and inserts them to be part of the new canonical chain and accumulates
|
// blocks and inserts them to be part of the new canonical chain and accumulates
|
||||||
// potential missing transactions and post an event about them.
|
// potential missing transactions and post an event about them.
|
||||||
|
//
|
||||||
// Note the new head block won't be processed here, callers need to handle it
|
// Note the new head block won't be processed here, callers need to handle it
|
||||||
// externally.
|
// externally.
|
||||||
// nolint:gocognit
|
func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error {
|
||||||
func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
|
||||||
var (
|
var (
|
||||||
newChain types.Blocks
|
newChain []*types.Header
|
||||||
oldChain types.Blocks
|
oldChain []*types.Header
|
||||||
commonBlock *types.Block
|
commonBlock *types.Header
|
||||||
|
|
||||||
deletedTxs []common.Hash
|
|
||||||
addedTxs []common.Hash
|
|
||||||
)
|
)
|
||||||
|
|
||||||
oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64())
|
|
||||||
|
|
||||||
if oldBlock == nil {
|
|
||||||
return errors.New("current head block missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
newBlock := newHead
|
|
||||||
|
|
||||||
// Reduce the longer chain to the same number as the shorter one
|
// Reduce the longer chain to the same number as the shorter one
|
||||||
if oldBlock.NumberU64() > newBlock.NumberU64() {
|
if oldHead.Number.Uint64() > newHead.Number.Uint64() {
|
||||||
// Old chain is longer, gather all transactions and logs as deleted ones
|
// Old chain is longer, gather all transactions and logs as deleted ones
|
||||||
for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) {
|
for ; oldHead != nil && oldHead.Number.Uint64() != newHead.Number.Uint64(); oldHead = bc.GetHeader(oldHead.ParentHash, oldHead.Number.Uint64()-1) {
|
||||||
oldChain = append(oldChain, oldBlock)
|
oldChain = append(oldChain, oldHead)
|
||||||
|
|
||||||
for _, tx := range oldBlock.Transactions() {
|
|
||||||
deletedTxs = append(deletedTxs, tx.Hash())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// New chain is longer, stash all blocks away for subsequent insertion
|
// New chain is longer, stash all blocks away for subsequent insertion
|
||||||
for ; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) {
|
for ; newHead != nil && newHead.Number.Uint64() != oldHead.Number.Uint64(); newHead = bc.GetHeader(newHead.ParentHash, newHead.Number.Uint64()-1) {
|
||||||
newChain = append(newChain, newBlock)
|
newChain = append(newChain, newHead)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if oldHead == nil {
|
||||||
if oldBlock == nil {
|
|
||||||
return errInvalidOldChain
|
return errInvalidOldChain
|
||||||
}
|
}
|
||||||
|
if newHead == nil {
|
||||||
if newBlock == nil {
|
|
||||||
return errInvalidNewChain
|
return errInvalidNewChain
|
||||||
}
|
}
|
||||||
// Both sides of the reorg are at the same number, reduce both until the common
|
// Both sides of the reorg are at the same number, reduce both until the common
|
||||||
// ancestor is found
|
// ancestor is found
|
||||||
for {
|
for {
|
||||||
// If the common ancestor was found, bail out
|
// If the common ancestor was found, bail out
|
||||||
if oldBlock.Hash() == newBlock.Hash() {
|
if oldHead.Hash() == newHead.Hash() {
|
||||||
commonBlock = oldBlock
|
commonBlock = oldHead
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Remove an old block as well as stash away a new block
|
// Remove an old block as well as stash away a new block
|
||||||
oldChain = append(oldChain, oldBlock)
|
oldChain = append(oldChain, oldHead)
|
||||||
|
newChain = append(newChain, newHead)
|
||||||
for _, tx := range oldBlock.Transactions() {
|
|
||||||
deletedTxs = append(deletedTxs, tx.Hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
newChain = append(newChain, newBlock)
|
|
||||||
|
|
||||||
// Step back with both chains
|
// Step back with both chains
|
||||||
oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1)
|
oldHead = bc.GetHeader(oldHead.ParentHash, oldHead.Number.Uint64()-1)
|
||||||
if oldBlock == nil {
|
if oldHead == nil {
|
||||||
return errInvalidOldChain
|
return errInvalidOldChain
|
||||||
}
|
}
|
||||||
|
newHead = bc.GetHeader(newHead.ParentHash, newHead.Number.Uint64()-1)
|
||||||
newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1)
|
if newHead == nil {
|
||||||
if newBlock == nil {
|
|
||||||
return errInvalidNewChain
|
return errInvalidNewChain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the user sees large reorgs
|
// Ensure the user sees large reorgs
|
||||||
if len(oldChain) > 0 && len(newChain) > 0 {
|
if len(oldChain) > 0 && len(newChain) > 0 {
|
||||||
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
||||||
|
|
@ -2971,8 +2953,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||||
msg = "Large chain reorg detected"
|
msg = "Large chain reorg detected"
|
||||||
logFn = log.Warn
|
logFn = log.Warn
|
||||||
}
|
}
|
||||||
|
logFn(msg, "number", commonBlock.Number, "hash", commonBlock.Hash(),
|
||||||
logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(),
|
|
||||||
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
|
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
|
||||||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||||
blockReorgDropMeter.Mark(int64(len(oldChain)))
|
blockReorgDropMeter.Mark(int64(len(oldChain)))
|
||||||
|
|
@ -2980,87 +2961,112 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||||
} else if len(newChain) > 0 {
|
} else if len(newChain) > 0 {
|
||||||
// Special case happens in the post merge stage that current head is
|
// Special case happens in the post merge stage that current head is
|
||||||
// the ancestor of new head while these two blocks are not consecutive
|
// the ancestor of new head while these two blocks are not consecutive
|
||||||
log.Info("Extend chain", "add", len(newChain), "number", newChain[0].Number(), "hash", newChain[0].Hash())
|
log.Info("Extend chain", "add", len(newChain), "number", newChain[0].Number, "hash", newChain[0].Hash())
|
||||||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||||
} else {
|
} else {
|
||||||
// len(newChain) == 0 && len(oldChain) > 0
|
// len(newChain) == 0 && len(oldChain) > 0
|
||||||
// rewind the canonical chain to a lower point.
|
// rewind the canonical chain to a lower point.
|
||||||
home, err := os.UserHomeDir()
|
log.Error("Impossible reorg, please file an issue", "oldnum", oldHead.Number, "oldhash", oldHead.Hash(), "oldblocks", len(oldChain), "newnum", newHead.Number, "newhash", newHead.Hash(), "newblocks", len(newChain))
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Impossible reorg : Unable to get user home dir", "Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
outPath := filepath.Join(home, "impossible-reorgs", fmt.Sprintf("%v-impossibleReorg", time.Now().Format(time.RFC3339)))
|
|
||||||
|
|
||||||
if _, err := os.Stat(outPath); errors.Is(err, os.ErrNotExist) {
|
|
||||||
err := os.MkdirAll(outPath, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Impossible reorg : Unable to create Dir", "Error", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = ExportBlocks(oldChain, filepath.Join(outPath, "oldChain.gz"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Impossible reorg : Unable to export oldChain", "Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ExportBlocks([]*types.Block{oldBlock}, filepath.Join(outPath, "oldBlock.gz"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Impossible reorg : Unable to export oldBlock", "Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ExportBlocks([]*types.Block{newBlock}, filepath.Join(outPath, "newBlock.gz"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Impossible reorg : Unable to export newBlock", "Error", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain))
|
|
||||||
}
|
}
|
||||||
// Acquire the tx-lookup lock before mutation. This step is essential
|
// Acquire the tx-lookup lock before mutation. This step is essential
|
||||||
// as the txlookups should be changed atomically, and all subsequent
|
// as the txlookups should be changed atomically, and all subsequent
|
||||||
// reads should be blocked until the mutation is complete.
|
// reads should be blocked until the mutation is complete.
|
||||||
bc.txLookupLock.Lock()
|
bc.txLookupLock.Lock()
|
||||||
|
|
||||||
// Insert the new chain segment in incremental order, from the old
|
// Reorg can be executed, start reducing the chain's old blocks and appending
|
||||||
// to the new. The new chain head (newChain[0]) is not inserted here,
|
// the new blocks
|
||||||
// as it will be handled separately outside of this function
|
var (
|
||||||
for i := len(newChain) - 1; i >= 1; i-- {
|
deletedTxs []common.Hash
|
||||||
// Insert the block in the canonical way, re-writing history
|
rebirthTxs []common.Hash
|
||||||
bc.writeHeadBlock(newChain[i])
|
|
||||||
|
|
||||||
// Collect the new added transactions.
|
deletedLogs []*types.Log
|
||||||
for _, tx := range newChain[i].Transactions() {
|
rebirthLogs []*types.Log
|
||||||
addedTxs = append(addedTxs, tx.Hash())
|
)
|
||||||
|
// Deleted log emission on the API uses forward order, which is borked, but
|
||||||
|
// we'll leave it in for legacy reasons.
|
||||||
|
//
|
||||||
|
// TODO(karalabe): This should be nuked out, no idea how, deprecate some APIs?
|
||||||
|
{
|
||||||
|
for i := len(oldChain) - 1; i >= 0; i-- {
|
||||||
|
block := bc.GetBlock(oldChain[i].Hash(), oldChain[i].Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
|
return errInvalidOldChain // Corrupt database, mostly here to avoid weird panics
|
||||||
|
}
|
||||||
|
if logs := bc.collectLogs(block, true); len(logs) > 0 {
|
||||||
|
deletedLogs = append(deletedLogs, logs...)
|
||||||
|
}
|
||||||
|
if len(deletedLogs) > 512 {
|
||||||
|
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||||
|
deletedLogs = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(deletedLogs) > 0 {
|
||||||
|
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Undo old blocks in reverse order
|
||||||
|
for i := 0; i < len(oldChain); i++ {
|
||||||
|
// Collect all the deleted transactions
|
||||||
|
block := bc.GetBlock(oldChain[i].Hash(), oldChain[i].Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
|
return errInvalidOldChain // Corrupt database, mostly here to avoid weird panics
|
||||||
|
}
|
||||||
|
for _, tx := range block.Transactions() {
|
||||||
|
deletedTxs = append(deletedTxs, tx.Hash())
|
||||||
|
}
|
||||||
|
// Collect deleted logs and emit them for new integrations
|
||||||
|
if logs := bc.collectLogs(block, true); len(logs) > 0 {
|
||||||
|
// Emit revertals latest first, older then
|
||||||
|
slices.Reverse(logs)
|
||||||
|
|
||||||
|
// TODO(karalabe): Hook into the reverse emission part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Apply new blocks in forward order
|
||||||
|
for i := len(newChain) - 1; i >= 1; i-- {
|
||||||
|
// Collect all the included transactions
|
||||||
|
block := bc.GetBlock(newChain[i].Hash(), newChain[i].Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
|
return errInvalidNewChain // Corrupt database, mostly here to avoid weird panics
|
||||||
|
}
|
||||||
|
for _, tx := range block.Transactions() {
|
||||||
|
rebirthTxs = append(rebirthTxs, tx.Hash())
|
||||||
|
}
|
||||||
|
// Collect inserted logs and emit them
|
||||||
|
if logs := bc.collectLogs(block, false); len(logs) > 0 {
|
||||||
|
rebirthLogs = append(rebirthLogs, logs...)
|
||||||
|
}
|
||||||
|
if len(rebirthLogs) > 512 {
|
||||||
|
bc.logsFeed.Send(rebirthLogs)
|
||||||
|
rebirthLogs = nil
|
||||||
|
}
|
||||||
|
// Update the head block
|
||||||
|
bc.writeHeadBlock(block)
|
||||||
|
}
|
||||||
|
if len(rebirthLogs) > 0 {
|
||||||
|
bc.logsFeed.Send(rebirthLogs)
|
||||||
|
}
|
||||||
// Delete useless indexes right now which includes the non-canonical
|
// Delete useless indexes right now which includes the non-canonical
|
||||||
// transaction indexes, canonical chain indexes which above the head.
|
// transaction indexes, canonical chain indexes which above the head.
|
||||||
var (
|
batch := bc.db.NewBatch()
|
||||||
indexesBatch = bc.db.NewBatch()
|
for _, tx := range types.HashDifference(deletedTxs, rebirthTxs) {
|
||||||
diffs = types.HashDifference(deletedTxs, addedTxs)
|
rawdb.DeleteTxLookupEntry(batch, tx)
|
||||||
)
|
|
||||||
for _, tx := range diffs {
|
|
||||||
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
|
|
||||||
}
|
}
|
||||||
// Delete all hash markers that are not part of the new canonical chain.
|
// Delete all hash markers that are not part of the new canonical chain.
|
||||||
// Because the reorg function does not handle new chain head, all hash
|
// Because the reorg function does not handle new chain head, all hash
|
||||||
// markers greater than or equal to new chain head should be deleted.
|
// markers greater than or equal to new chain head should be deleted.
|
||||||
number := commonBlock.NumberU64()
|
number := commonBlock.Number
|
||||||
if len(newChain) > 1 {
|
if len(newChain) > 1 {
|
||||||
number = newChain[1].NumberU64()
|
number = newChain[1].Number
|
||||||
}
|
}
|
||||||
|
for i := number.Uint64() + 1; ; i++ {
|
||||||
for i := number + 1; ; i++ {
|
|
||||||
hash := rawdb.ReadCanonicalHash(bc.db, i)
|
hash := rawdb.ReadCanonicalHash(bc.db, i)
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
rawdb.DeleteCanonicalHash(batch, i)
|
||||||
rawdb.DeleteCanonicalHash(indexesBatch, i)
|
|
||||||
}
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
if err := indexesBatch.Write(); err != nil {
|
|
||||||
log.Crit("Failed to delete useless indexes", "err", err)
|
log.Crit("Failed to delete useless indexes", "err", err)
|
||||||
}
|
}
|
||||||
// Reset the tx lookup cache to clear stale txlookup cache.
|
// Reset the tx lookup cache to clear stale txlookup cache.
|
||||||
|
|
@ -3069,88 +3075,6 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||||
// Release the tx-lookup lock after mutation.
|
// Release the tx-lookup lock after mutation.
|
||||||
bc.txLookupLock.Unlock()
|
bc.txLookupLock.Unlock()
|
||||||
|
|
||||||
// Send out events for logs from the old canon chain, and 'reborn'
|
|
||||||
// logs from the new canon chain. The number of logs can be very
|
|
||||||
// high, so the events are sent in batches of size around 512.
|
|
||||||
|
|
||||||
// Deleted logs + blocks:
|
|
||||||
var deletedLogs []*types.Log
|
|
||||||
|
|
||||||
for i := len(oldChain) - 1; i >= 0; i-- {
|
|
||||||
// Also send event for blocks removed from the canon chain.
|
|
||||||
bc.chainSideFeed.Send(ChainSideEvent{Block: oldChain[i]})
|
|
||||||
|
|
||||||
// Collect deleted logs for notification
|
|
||||||
if logs := bc.collectLogs(oldChain[i], true); len(logs) > 0 {
|
|
||||||
deletedLogs = append(deletedLogs, logs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(deletedLogs) > 512 {
|
|
||||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
|
||||||
deletedLogs = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(deletedLogs) > 0 {
|
|
||||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
|
||||||
}
|
|
||||||
|
|
||||||
// New logs:
|
|
||||||
var rebirthLogs []*types.Log
|
|
||||||
|
|
||||||
for i := len(newChain) - 1; i >= 1; i-- {
|
|
||||||
if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 {
|
|
||||||
rebirthLogs = append(rebirthLogs, logs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rebirthLogs) > 512 {
|
|
||||||
bc.logsFeed.Send(rebirthLogs)
|
|
||||||
rebirthLogs = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rebirthLogs) > 0 {
|
|
||||||
bc.logsFeed.Send(rebirthLogs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExportBlocks exports blocks into the specified file, truncating any data
|
|
||||||
// already present in the file.
|
|
||||||
func ExportBlocks(blocks []*types.Block, fn string) error {
|
|
||||||
log.Info("Exporting blockchain", "file", fn)
|
|
||||||
|
|
||||||
// Open the file handle and potentially wrap with a gzip stream
|
|
||||||
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
var writer io.Writer = fh
|
|
||||||
if strings.HasSuffix(fn, ".gz") {
|
|
||||||
writer = gzip.NewWriter(writer)
|
|
||||||
defer writer.(*gzip.Writer).Close()
|
|
||||||
}
|
|
||||||
// Iterate over the blocks and export them
|
|
||||||
if err := ExportN(writer, blocks); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("Exported blocks", "file", fn)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExportBlock writes a block to the given writer.
|
|
||||||
func ExportN(w io.Writer, blocks []*types.Block) error {
|
|
||||||
for _, block := range blocks {
|
|
||||||
if err := block.EncodeRLP(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3190,7 +3114,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if head.ParentHash() != bc.CurrentBlock().Hash() {
|
if head.ParentHash() != bc.CurrentBlock().Hash() {
|
||||||
if err := bc.reorg(bc.CurrentBlock(), head); err != nil {
|
if err := bc.reorg(bc.CurrentBlock(), head.Header()); err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3199,13 +3123,11 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
||||||
|
|
||||||
// Emit events
|
// Emit events
|
||||||
logs := bc.collectLogs(head, false)
|
logs := bc.collectLogs(head, false)
|
||||||
bc.chainFeed.Send(ChainEvent{Block: head, Hash: head.Hash(), Logs: logs})
|
bc.chainFeed.Send(ChainEvent{Header: head.Header()})
|
||||||
|
|
||||||
if len(logs) > 0 {
|
if len(logs) > 0 {
|
||||||
bc.logsFeed.Send(logs)
|
bc.logsFeed.Send(logs)
|
||||||
}
|
}
|
||||||
|
bc.chainHeadFeed.Send(ChainHeadEvent{Header: head.Header()})
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: head})
|
|
||||||
|
|
||||||
context := []interface{}{
|
context := []interface{}{
|
||||||
"number", head.Number(),
|
"number", head.Number(),
|
||||||
|
|
|
||||||
|
|
@ -484,11 +484,6 @@ func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Su
|
||||||
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
|
|
||||||
func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
|
|
||||||
return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubscribeLogsEvent registers a subscription of []*types.Log.
|
// SubscribeLogsEvent registers a subscription of []*types.Log.
|
||||||
func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
||||||
return bc.scope.Track(bc.logsFeed.Subscribe(ch))
|
return bc.scope.Track(bc.logsFeed.Subscribe(ch))
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"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/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1804,15 +1805,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
db, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close() // Might double close, should be fine
|
defer db.Close() // Might double close, should be fine
|
||||||
|
|
||||||
|
|
@ -1891,15 +1890,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
db, err = rawdb.Open(rawdb.OpenOptions{
|
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent database: %v", err)
|
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to reopen persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|
@ -1958,14 +1955,13 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
db, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close() // Might double close, should be fine
|
defer db.Close() // Might double close, should be fine
|
||||||
|
|
||||||
|
|
@ -2017,15 +2013,13 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
db, err = rawdb.Open(rawdb.OpenOptions{
|
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent database: %v", err)
|
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to reopen persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ 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/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||||
|
|
@ -1968,15 +1969,13 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
db, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"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/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -66,15 +67,13 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
db, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
// Initialize a fresh chain
|
// Initialize a fresh chain
|
||||||
var (
|
var (
|
||||||
|
|
@ -260,15 +259,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
chain.triedb.Close()
|
chain.triedb.Close()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
newdb, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false)
|
||||||
Directory: snaptest.datadir,
|
|
||||||
AncientsDirectory: snaptest.ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
IsLastOffset: false,
|
|
||||||
DisableFreeze: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
newdb, err := rawdb.NewDatabaseWithFreezer(pdb, snaptest.ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer newdb.Close()
|
defer newdb.Close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
gomath "math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -29,7 +30,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"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/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"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/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -1511,94 +1512,6 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReorgSideEvent(t *testing.T) {
|
|
||||||
testReorgSideEvent(t, rawdb.HashScheme)
|
|
||||||
testReorgSideEvent(t, rawdb.PathScheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testReorgSideEvent(t *testing.T, scheme string) {
|
|
||||||
var (
|
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
|
||||||
gspec = &Genesis{
|
|
||||||
Config: params.TestChainConfig,
|
|
||||||
Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
|
|
||||||
}
|
|
||||||
signer = types.LatestSigner(gspec.Config)
|
|
||||||
)
|
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
|
||||||
defer blockchain.Stop()
|
|
||||||
|
|
||||||
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {})
|
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
|
||||||
t.Fatalf("failed to insert chain: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, replacementBlocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, gen *BlockGen) {
|
|
||||||
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, nil), signer, key1)
|
|
||||||
|
|
||||||
if i == 2 {
|
|
||||||
gen.OffsetTime(-9)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create tx: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gen.AddTx(tx)
|
|
||||||
})
|
|
||||||
chainSideCh := make(chan ChainSideEvent, 64)
|
|
||||||
blockchain.SubscribeChainSideEvent(chainSideCh)
|
|
||||||
|
|
||||||
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
|
|
||||||
t.Fatalf("failed to insert chain: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// first two block of the secondary chain are for a brief moment considered
|
|
||||||
// side chains because up to that point the first one is considered the
|
|
||||||
// heavier chain.
|
|
||||||
expectedSideHashes := map[common.Hash]bool{
|
|
||||||
replacementBlocks[0].Hash(): true,
|
|
||||||
replacementBlocks[1].Hash(): true,
|
|
||||||
chain[0].Hash(): true,
|
|
||||||
chain[1].Hash(): true,
|
|
||||||
chain[2].Hash(): true,
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
|
|
||||||
const timeoutDura = 10 * time.Second
|
|
||||||
timeout := time.NewTimer(timeoutDura)
|
|
||||||
done:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case ev := <-chainSideCh:
|
|
||||||
block := ev.Block
|
|
||||||
if _, ok := expectedSideHashes[block.Hash()]; !ok {
|
|
||||||
t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash())
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
|
|
||||||
if i == len(expectedSideHashes) {
|
|
||||||
timeout.Stop()
|
|
||||||
|
|
||||||
break done
|
|
||||||
}
|
|
||||||
timeout.Reset(timeoutDura)
|
|
||||||
|
|
||||||
case <-timeout.C:
|
|
||||||
t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure no more events are fired
|
|
||||||
select {
|
|
||||||
case e := <-chainSideCh:
|
|
||||||
t.Errorf("unexpected event fired: %v", e)
|
|
||||||
case <-time.After(250 * time.Millisecond):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests if the canonical block can be fetched from the database during chain insertion.
|
// Tests if the canonical block can be fetched from the database during chain insertion.
|
||||||
func TestCanonicalBlockRetrieval(t *testing.T) {
|
func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||||
testCanonicalBlockRetrieval(t, rawdb.HashScheme)
|
testCanonicalBlockRetrieval(t, rawdb.HashScheme)
|
||||||
|
|
@ -2277,11 +2190,11 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
|
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: &chainConfig,
|
Config: &chainConfig,
|
||||||
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(gomath.MaxInt64)}},
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
mergeBlock = math.MaxInt32
|
mergeBlock = gomath.MaxInt32
|
||||||
)
|
)
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||||
|
|
@ -2582,7 +2495,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||||
Config: &chainConfig,
|
Config: &chainConfig,
|
||||||
}
|
}
|
||||||
engine = beacon.New(ethash.NewFaker())
|
engine = beacon.New(ethash.NewFaker())
|
||||||
mergeBlock = uint64(math.MaxUint64)
|
mergeBlock = uint64(gomath.MaxUint64)
|
||||||
)
|
)
|
||||||
// Apply merging since genesis
|
// Apply merging since genesis
|
||||||
if mergeHeight == 0 {
|
if mergeHeight == 0 {
|
||||||
|
|
@ -3059,13 +2972,13 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := path.Join(datadir, "ancient")
|
ancient := path.Join(datadir, "ancient")
|
||||||
|
|
||||||
db, err := rawdb.Open(rawdb.OpenOptions{
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
Directory: datadir,
|
|
||||||
AncientsDirectory: ancient,
|
|
||||||
Ephemeral: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
|
}
|
||||||
|
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|
@ -4577,11 +4490,7 @@ func TestEIP3651(t *testing.T) {
|
||||||
gspec.Config.BerlinBlock = common.Big0
|
gspec.Config.BerlinBlock = common.Big0
|
||||||
gspec.Config.LondonBlock = common.Big0
|
gspec.Config.LondonBlock = common.Big0
|
||||||
gspec.Config.TerminalTotalDifficulty = common.Big0
|
gspec.Config.TerminalTotalDifficulty = common.Big0
|
||||||
gspec.Config.TerminalTotalDifficultyPassed = true
|
gspec.Config.ShanghaiTime = u64(0)
|
||||||
gspec.Config.ShanghaiBlock = common.Big0
|
|
||||||
// gspec.Config.CancunBlock = common.Big0
|
|
||||||
// gspec.Config.PragueBlock = common.Big0
|
|
||||||
// gspec.Config.VerkleBlock = common.Big0
|
|
||||||
signer := types.LatestSigner(gspec.Config)
|
signer := types.LatestSigner(gspec.Config)
|
||||||
|
|
||||||
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
||||||
|
|
@ -4639,3 +4548,87 @@ func TestEIP3651(t *testing.T) {
|
||||||
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
|
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
|
||||||
|
var depositsGeneratorCode = common.FromHex("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033")
|
||||||
|
|
||||||
|
// This is a smoke test for EIP-7685 requests added in the Prague fork. The test first
|
||||||
|
// creates a block containing requests, and then inserts it into the chain to run
|
||||||
|
// validation.
|
||||||
|
func TestPragueRequests(t *testing.T) {
|
||||||
|
var (
|
||||||
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
config = *params.MergedTestChainConfig
|
||||||
|
signer = types.LatestSigner(&config)
|
||||||
|
engine = beacon.NewFaker()
|
||||||
|
)
|
||||||
|
gspec := &Genesis{
|
||||||
|
Config: &config,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
addr1: {Balance: big.NewInt(9999900000000000)},
|
||||||
|
config.DepositContractAddress: {Code: depositsGeneratorCode},
|
||||||
|
params.WithdrawalQueueAddress: {Code: params.WithdrawalQueueCode},
|
||||||
|
params.ConsolidationQueueAddress: {Code: params.ConsolidationQueueCode},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
||||||
|
// create deposit
|
||||||
|
depositTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
||||||
|
ChainID: gspec.Config.ChainID,
|
||||||
|
Nonce: 0,
|
||||||
|
To: &config.DepositContractAddress,
|
||||||
|
Gas: 500_000,
|
||||||
|
GasFeeCap: newGwei(5),
|
||||||
|
GasTipCap: big.NewInt(2),
|
||||||
|
})
|
||||||
|
b.AddTx(depositTx)
|
||||||
|
|
||||||
|
// create withdrawal request
|
||||||
|
withdrawalTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
||||||
|
ChainID: gspec.Config.ChainID,
|
||||||
|
Nonce: 1,
|
||||||
|
To: ¶ms.WithdrawalQueueAddress,
|
||||||
|
Gas: 500_000,
|
||||||
|
GasFeeCap: newGwei(5),
|
||||||
|
GasTipCap: big.NewInt(2),
|
||||||
|
Value: newGwei(1),
|
||||||
|
Data: common.FromHex("b917cfdc0d25b72d55cf94db328e1629b7f4fde2c30cdacf873b664416f76a0c7f7cc50c9f72a3cb84be88144cde91250000000000000d80"),
|
||||||
|
})
|
||||||
|
b.AddTx(withdrawalTx)
|
||||||
|
|
||||||
|
// create consolidation request
|
||||||
|
consolidationTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
||||||
|
ChainID: gspec.Config.ChainID,
|
||||||
|
Nonce: 2,
|
||||||
|
To: ¶ms.ConsolidationQueueAddress,
|
||||||
|
Gas: 500_000,
|
||||||
|
GasFeeCap: newGwei(5),
|
||||||
|
GasTipCap: big.NewInt(2),
|
||||||
|
Value: newGwei(1),
|
||||||
|
Data: common.FromHex("b917cfdc0d25b72d55cf94db328e1629b7f4fde2c30cdacf873b664416f76a0c7f7cc50c9f72a3cb84be88144cde9125b9812f7d0b1f2f969b52bbb2d316b0c2fa7c9dba85c428c5e6c27766bcc4b0c6e874702ff1eb1c7024b08524a9771601"),
|
||||||
|
})
|
||||||
|
b.AddTx(consolidationTx)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check block has the correct requests hash.
|
||||||
|
rh := blocks[0].RequestsHash()
|
||||||
|
if rh == nil {
|
||||||
|
t.Fatal("block has nil requests hash")
|
||||||
|
}
|
||||||
|
expectedRequestsHash := common.HexToHash("0x06ffb72b9f0823510b128bca6cd4f96f59b745de6791e9fc350b596e7605101e")
|
||||||
|
if *rh != expectedRequestsHash {
|
||||||
|
t.Fatalf("block has wrong requestsHash %v, want %v", *rh, expectedRequestsHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert block to check validation.
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
|
}
|
||||||
|
defer chain.Stop()
|
||||||
|
if n, err := chain.InsertChain(blocks); err != nil {
|
||||||
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,21 +227,18 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainH
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if ev.Header.ParentHash != prevHash {
|
||||||
header := ev.Block.Header()
|
|
||||||
if header.ParentHash != prevHash {
|
|
||||||
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
|
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
|
||||||
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
|
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
|
||||||
if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash {
|
if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash {
|
||||||
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, header); h != nil {
|
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, ev.Header); h != nil {
|
||||||
c.newHead(h.Number.Uint64(), true)
|
c.newHead(h.Number.Uint64(), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c.newHead(ev.Header.Number.Uint64(), false)
|
||||||
|
|
||||||
c.newHead(header.Number.Uint64(), false)
|
prevHeader, prevHash = ev.Header, ev.Header.Hash()
|
||||||
|
|
||||||
prevHeader, prevHash = header, header.Hash()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -359,18 +359,34 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
var requests types.Requests
|
var requests [][]byte
|
||||||
if config.IsPrague(b.header.Number) && config.Bor == nil {
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
|
// EIP-6110 deposits
|
||||||
|
var blockLogs []*types.Log
|
||||||
for _, r := range b.receipts {
|
for _, r := range b.receipts {
|
||||||
d, err := ParseDepositLogs(r.Logs, config)
|
blockLogs = append(blockLogs, r.Logs...)
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
|
||||||
}
|
|
||||||
requests = append(requests, d...)
|
|
||||||
}
|
}
|
||||||
|
depositRequests, err := ParseDepositLogs(blockLogs, config)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
||||||
|
}
|
||||||
|
requests = append(requests, depositRequests)
|
||||||
|
// create EVM for system calls
|
||||||
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
|
||||||
|
// EIP-7002 withdrawals
|
||||||
|
withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb)
|
||||||
|
requests = append(requests, withdrawalRequests)
|
||||||
|
// EIP-7251 consolidations
|
||||||
|
consolidationRequests := ProcessConsolidationQueue(vmenv, statedb)
|
||||||
|
requests = append(requests, consolidationRequests)
|
||||||
|
}
|
||||||
|
if requests != nil {
|
||||||
|
reqHash := types.CalcRequestsHash(requests)
|
||||||
|
b.header.RequestsHash = &reqHash
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
|
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
|
||||||
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
@ -461,16 +477,15 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
// Save pre state for proof generation
|
// Save pre state for proof generation
|
||||||
// preState := statedb.Copy()
|
// preState := statedb.Copy()
|
||||||
|
|
||||||
// TODO uncomment when the 2935 PR is merged
|
// Pre-execution system calls.
|
||||||
// if config.IsPrague(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
// if !config.IsPrague(b.parent.Number(), b.parent.Time()) {
|
// EIP-2935
|
||||||
// Transition case: insert all 256 ancestors
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
// InsertBlockHashHistoryAtEip2935Fork(statedb, b.header.Number.Uint64()-1, b.header.ParentHash, chainreader)
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
|
||||||
// } else {
|
ProcessParentBlockHash(b.header.ParentHash, vmenv, statedb)
|
||||||
// ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash)
|
}
|
||||||
// }
|
|
||||||
// }
|
// Execute any user modifications to the block.
|
||||||
// Execute any user modifications to the block
|
|
||||||
if gen != nil {
|
if gen != nil {
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
@ -484,7 +499,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write state changes to db
|
// Write state changes to DB.
|
||||||
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("state write error: %v", err))
|
panic(fmt.Sprintf("state write error: %v", err))
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
)
|
)
|
||||||
|
|
||||||
config.TerminalTotalDifficultyPassed = true
|
|
||||||
config.TerminalTotalDifficulty = common.Big0
|
config.TerminalTotalDifficulty = common.Big0
|
||||||
config.ShanghaiBlock = common.Big0
|
config.ShanghaiBlock = common.Big0
|
||||||
config.CancunBlock = common.Big0
|
config.CancunBlock = common.Big0
|
||||||
|
|
|
||||||
|
|
@ -17,27 +17,19 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
|
// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
|
||||||
type NewTxsEvent struct{ Txs []*types.Transaction }
|
type NewTxsEvent struct{ Txs []*types.Transaction }
|
||||||
|
|
||||||
// NewMinedBlockEvent is posted when a block has been imported.
|
|
||||||
type NewMinedBlockEvent struct{ Block *types.Block }
|
|
||||||
|
|
||||||
// RemovedLogsEvent is posted when a reorg happens
|
// RemovedLogsEvent is posted when a reorg happens
|
||||||
type RemovedLogsEvent struct{ Logs []*types.Log }
|
type RemovedLogsEvent struct{ Logs []*types.Log }
|
||||||
|
|
||||||
type ChainEvent struct {
|
type ChainEvent struct {
|
||||||
Block *types.Block
|
Header *types.Header
|
||||||
Hash common.Hash
|
|
||||||
Logs []*types.Log
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChainSideEvent struct {
|
type ChainHeadEvent struct {
|
||||||
Block *types.Block
|
Header *types.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChainHeadEvent struct{ Block *types.Block }
|
|
||||||
|
|
|
||||||
|
|
@ -364,24 +364,25 @@ func TestTimeBasedForkInGenesis(t *testing.T) {
|
||||||
forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
|
forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
|
||||||
config = func(shanghai, cancun uint64) *params.ChainConfig {
|
config = func(shanghai, cancun uint64) *params.ChainConfig {
|
||||||
return ¶ms.ChainConfig{
|
return ¶ms.ChainConfig{
|
||||||
ChainID: big.NewInt(1337),
|
ChainID: big.NewInt(1337),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: true,
|
DAOForkSupport: true,
|
||||||
EIP150Block: big.NewInt(0),
|
EIP150Block: big.NewInt(0),
|
||||||
EIP155Block: big.NewInt(0),
|
EIP155Block: big.NewInt(0),
|
||||||
EIP158Block: big.NewInt(0),
|
EIP158Block: big.NewInt(0),
|
||||||
ByzantiumBlock: big.NewInt(0),
|
ByzantiumBlock: big.NewInt(0),
|
||||||
ConstantinopleBlock: big.NewInt(0),
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
PetersburgBlock: big.NewInt(0),
|
PetersburgBlock: big.NewInt(0),
|
||||||
IstanbulBlock: big.NewInt(0),
|
IstanbulBlock: big.NewInt(0),
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
TerminalTotalDifficultyPassed: true,
|
MergeNetsplitBlock: big.NewInt(0),
|
||||||
MergeNetsplitBlock: big.NewInt(0),
|
ShanghaiTime: &shanghai,
|
||||||
Ethash: new(params.EthashConfig),
|
CancunTime: &cancun,
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,6 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
withdrawals []*types.Withdrawal
|
withdrawals []*types.Withdrawal
|
||||||
requests types.Requests
|
|
||||||
)
|
)
|
||||||
if conf := g.Config; conf != nil {
|
if conf := g.Config; conf != nil {
|
||||||
num := big.NewInt(int64(g.Number))
|
num := big.NewInt(int64(g.Number))
|
||||||
|
|
@ -512,12 +511,13 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
head.BlobGasUsed = new(uint64)
|
head.BlobGasUsed = new(uint64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if conf.IsPrague(num) {
|
if conf.IsPrague(num, g.Timestamp) {
|
||||||
head.RequestsHash = &types.EmptyRequestsHash
|
emptyRequests := [][]byte{{0x00}, {0x01}, {0x02}}
|
||||||
requests = make(types.Requests, 0)
|
rhash := types.CalcRequestsHash(emptyRequests)
|
||||||
|
head.RequestsHash = &rhash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
|
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit writes the block and state of a genesis specification to the database.
|
// Commit writes the block and state of a genesis specification to the database.
|
||||||
|
|
@ -680,10 +680,11 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
||||||
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
|
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
|
||||||
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
||||||
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
||||||
// Pre-deploy EIP-4788 system contract
|
// Pre-deploy system contracts
|
||||||
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
||||||
// Pre-deploy EIP-2935 history contract.
|
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0},
|
||||||
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0},
|
params.WithdrawalQueueAddress: {Nonce: 1, Code: params.WithdrawalQueueCode, Balance: common.Big0},
|
||||||
|
params.ConsolidationQueueAddress: {Nonce: 1, Code: params.ConsolidationQueueCode, Balance: common.Big0},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if faucet != nil {
|
if faucet != nil {
|
||||||
|
|
|
||||||
|
|
@ -266,31 +266,30 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
t.Skip("verkle trie is not yet supported in bor")
|
t.Skip("verkle trie is not yet supported in bor")
|
||||||
var verkleTime uint64 = 0
|
var verkleTime uint64 = 0
|
||||||
verkleConfig := ¶ms.ChainConfig{
|
verkleConfig := ¶ms.ChainConfig{
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: false,
|
DAOForkSupport: false,
|
||||||
EIP150Block: big.NewInt(0),
|
EIP150Block: big.NewInt(0),
|
||||||
EIP155Block: big.NewInt(0),
|
EIP155Block: big.NewInt(0),
|
||||||
EIP158Block: big.NewInt(0),
|
EIP158Block: big.NewInt(0),
|
||||||
ByzantiumBlock: big.NewInt(0),
|
ByzantiumBlock: big.NewInt(0),
|
||||||
ConstantinopleBlock: big.NewInt(0),
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
PetersburgBlock: big.NewInt(0),
|
PetersburgBlock: big.NewInt(0),
|
||||||
IstanbulBlock: big.NewInt(0),
|
IstanbulBlock: big.NewInt(0),
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
ArrowGlacierBlock: big.NewInt(0),
|
ArrowGlacierBlock: big.NewInt(0),
|
||||||
GrayGlacierBlock: big.NewInt(0),
|
GrayGlacierBlock: big.NewInt(0),
|
||||||
MergeNetsplitBlock: nil,
|
MergeNetsplitBlock: nil,
|
||||||
ShanghaiBlock: big.NewInt(0),
|
ShanghaiTime: &verkleTime,
|
||||||
CancunBlock: big.NewInt(0),
|
CancunTime: &verkleTime,
|
||||||
PragueBlock: big.NewInt(0),
|
PragueTime: &verkleTime,
|
||||||
VerkleBlock: big.NewInt(0),
|
VerkleTime: &verkleTime,
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
TerminalTotalDifficultyPassed: true,
|
Ethash: nil,
|
||||||
Ethash: nil,
|
Clique: nil,
|
||||||
Clique: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
genesis := &Genesis{
|
genesis := &Genesis{
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue