mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
Merge branch 'ethereum:master' into portal
This commit is contained in:
commit
65f1f82e74
31 changed files with 6956 additions and 496 deletions
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
before_install:
|
||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
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 Linux Azure uploads
|
||||
- stage: build
|
||||
|
|
|
|||
|
|
@ -338,8 +338,22 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
return common.Address{}, nil, err
|
||||
}
|
||||
} 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 {
|
||||
return common.Address{}, nil, err
|
||||
if tx.Type() == types.DynamicFeeTxType {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
payload := append(path, txrlp...)
|
||||
|
|
@ -353,7 +367,9 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
|
||||
// https://github.com/LedgerHQ/app-ethereum/issues/409
|
||||
chunk := 255
|
||||
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
|
||||
if tx.Type() == types.LegacyTxType {
|
||||
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
|
||||
}
|
||||
}
|
||||
|
||||
for len(payload) > 0 {
|
||||
|
|
@ -381,8 +397,11 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
if chainID == nil {
|
||||
signer = new(types.HomesteadSigner)
|
||||
} else {
|
||||
signer = types.NewEIP155Signer(chainID)
|
||||
signature[64] -= byte(chainID.Uint64()*2 + 35)
|
||||
signer = types.LatestSignerForChainID(chainID)
|
||||
// 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)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,25 +17,22 @@
|
|||
package blsync
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/beacon/light"
|
||||
"github.com/ethereum/go-ethereum/beacon/light/api"
|
||||
"github.com/ethereum/go-ethereum/beacon/light/request"
|
||||
"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/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common/mclock"
|
||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
urls []string
|
||||
customHeader map[string]string
|
||||
chainConfig *lightClientConfig
|
||||
config *params.ClientConfig
|
||||
scheduler *request.Scheduler
|
||||
blockSync *beaconBlockSync
|
||||
engineRPC *rpc.Client
|
||||
|
|
@ -44,34 +41,18 @@ type Client struct {
|
|||
engineClient *engineClient
|
||||
}
|
||||
|
||||
func NewClient(ctx *cli.Context) *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])
|
||||
}
|
||||
|
||||
func NewClient(config params.ClientConfig) *Client {
|
||||
// create data structures
|
||||
var (
|
||||
db = memorydb.New()
|
||||
threshold = ctx.Int(utils.BeaconThresholdFlag.Name)
|
||||
committeeChain = light.NewCommitteeChain(db, chainConfig.ChainConfig, threshold, !ctx.Bool(utils.BeaconNoFilterFlag.Name))
|
||||
headTracker = light.NewHeadTracker(committeeChain, threshold)
|
||||
committeeChain = light.NewCommitteeChain(db, &config.ChainConfig, config.Threshold, !config.NoFilter)
|
||||
headTracker = light.NewHeadTracker(committeeChain, config.Threshold)
|
||||
)
|
||||
headSync := sync.NewHeadSync(headTracker, committeeChain)
|
||||
|
||||
// set up scheduler and sync modules
|
||||
scheduler := request.NewScheduler()
|
||||
checkpointInit := sync.NewCheckpointInit(committeeChain, chainConfig.Checkpoint)
|
||||
checkpointInit := sync.NewCheckpointInit(committeeChain, config.Checkpoint)
|
||||
forwardSync := sync.NewForwardUpdateSync(committeeChain)
|
||||
beaconBlockSync := newBeaconBlockSync(headTracker)
|
||||
scheduler.RegisterTarget(headTracker)
|
||||
|
|
@ -83,9 +64,9 @@ func NewClient(ctx *cli.Context) *Client {
|
|||
|
||||
return &Client{
|
||||
scheduler: scheduler,
|
||||
urls: ctx.StringSlice(utils.BeaconApiFlag.Name),
|
||||
customHeader: customHeader,
|
||||
chainConfig: &chainConfig,
|
||||
urls: config.Apis,
|
||||
customHeader: config.CustomHeader,
|
||||
config: &config,
|
||||
blockSync: beaconBlockSync,
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +78,7 @@ func (c *Client) SetEngineRPC(engine *rpc.Client) {
|
|||
func (c *Client) Start() error {
|
||||
headCh := make(chan types.ChainHeadEvent, 16)
|
||||
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()
|
||||
for _, url := range c.urls {
|
||||
|
|
|
|||
|
|
@ -1,129 +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("0x6509b691f4de4f7b083f2784938fd52f0e131675432b3fd85ea549af9aebd3d0"),
|
||||
}
|
||||
|
||||
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("0x456e85f5608afab3465a0580bff8572255f6d97af0c5f939e3f7536b5edb2d3f"),
|
||||
}
|
||||
|
||||
HoleskyConfig = lightClientConfig{
|
||||
ChainConfig: (&types.ChainConfig{
|
||||
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
||||
GenesisTime: 1695902400,
|
||||
}).
|
||||
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}),
|
||||
Checkpoint: common.HexToHash("0x6456a1317f54d4b4f2cb5bc9d153b5af0988fe767ef0609f0236cf29030bcff7"),
|
||||
}
|
||||
)
|
||||
|
||||
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
||||
var config lightClientConfig
|
||||
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
||||
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.HoleskyFlag, utils.BeaconConfigFlag)
|
||||
switch {
|
||||
case ctx.Bool(utils.MainnetFlag.Name):
|
||||
config = MainnetConfig
|
||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
||||
config = SepoliaConfig
|
||||
case ctx.Bool(utils.HoleskyFlag.Name):
|
||||
config = HoleskyConfig
|
||||
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"
|
||||
|
||||
"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/common"
|
||||
ctypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
|
@ -31,14 +32,14 @@ import (
|
|||
)
|
||||
|
||||
type engineClient struct {
|
||||
config *lightClientConfig
|
||||
config *params.ClientConfig
|
||||
rpc *rpc.Client
|
||||
rootCtx context.Context
|
||||
cancelRoot context.CancelFunc
|
||||
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())
|
||||
ec := &engineClient{
|
||||
config: config,
|
||||
|
|
|
|||
|
|
@ -76,24 +76,24 @@ type CommitteeChain struct {
|
|||
unixNano func() int64 // system clock (simulated clock in tests)
|
||||
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
|
||||
|
||||
config *types.ChainConfig
|
||||
config *params.ChainConfig
|
||||
minimumUpdateScore types.UpdateScore
|
||||
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
|
||||
}
|
||||
|
||||
// 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() })
|
||||
}
|
||||
|
||||
// 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()) })
|
||||
}
|
||||
|
||||
// newCommitteeChain creates a new CommitteeChain with the option of replacing the
|
||||
// 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{
|
||||
committeeCache: lru.NewCache[uint64, syncCommittee](10),
|
||||
db: db,
|
||||
|
|
@ -505,7 +505,7 @@ func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time
|
|||
if committee == 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 false, age, nil
|
||||
|
|
|
|||
|
|
@ -31,15 +31,15 @@ var (
|
|||
testGenesis = newTestGenesis()
|
||||
testGenesis2 = newTestGenesis()
|
||||
|
||||
tfBase = newTestForks(testGenesis, types.Forks{
|
||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
||||
tfBase = newTestForks(testGenesis, params.Forks{
|
||||
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||
})
|
||||
tfAlternative = newTestForks(testGenesis, types.Forks{
|
||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
||||
&types.Fork{Epoch: 0x700, Version: []byte{1}},
|
||||
tfAlternative = newTestForks(testGenesis, params.Forks{
|
||||
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||
¶ms.Fork{Epoch: 0x700, Version: []byte{1}},
|
||||
})
|
||||
tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{
|
||||
&types.Fork{Epoch: 0, Version: []byte{0}},
|
||||
tfAnotherGenesis = newTestForks(testGenesis2, params.Forks{
|
||||
¶ms.Fork{Epoch: 0, Version: []byte{0}},
|
||||
})
|
||||
|
||||
tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false)
|
||||
|
|
@ -226,13 +226,13 @@ type committeeChainTest struct {
|
|||
t *testing.T
|
||||
db *memorydb.Database
|
||||
clock *mclock.Simulated
|
||||
config types.ChainConfig
|
||||
config params.ChainConfig
|
||||
signerThreshold int
|
||||
enforceTime bool
|
||||
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{
|
||||
t: t,
|
||||
db: memorydb.New(),
|
||||
|
|
@ -298,20 +298,20 @@ func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint
|
|||
c.verifySignedHeader(tc, float64(end)+1.5, false)
|
||||
}
|
||||
|
||||
func newTestGenesis() types.ChainConfig {
|
||||
var config types.ChainConfig
|
||||
func newTestGenesis() params.ChainConfig {
|
||||
var config params.ChainConfig
|
||||
rand.Read(config.GenesisValidatorsRoot[:])
|
||||
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 {
|
||||
config.AddFork(fork.Name, fork.Epoch, fork.Version)
|
||||
}
|
||||
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{
|
||||
config: config,
|
||||
}
|
||||
|
|
@ -337,7 +337,7 @@ type testPeriod struct {
|
|||
|
||||
type testCommitteeChain struct {
|
||||
periods []testPeriod
|
||||
config types.ChainConfig
|
||||
config params.ChainConfig
|
||||
}
|
||||
|
||||
func (tc *testCommitteeChain) fillCommittees(begin, end int) {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func GenerateTestCommittee() *types.SerializedSyncCommittee {
|
|||
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.NextSyncCommitteeRoot = nextCommittee.Root()
|
||||
var attestedHeader types.Header
|
||||
|
|
@ -48,9 +48,9 @@ func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nex
|
|||
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)
|
||||
signingRoot, _ := config.Forks.SigningRoot(header)
|
||||
signingRoot, _ := config.Forks.SigningRoot(header.Epoch(), header.Hash())
|
||||
c, _ := dummyVerifier{}.deserializeSyncCommittee(committee)
|
||||
return types.SignedHeader{
|
||||
Header: header,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package types
|
||||
package params
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
|
@ -39,81 +39,13 @@ const syncCommitteeDomain = 7
|
|||
|
||||
var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"}
|
||||
|
||||
// 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(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
|
||||
// ClientConfig contains beacon light client configuration.
|
||||
type ClientConfig struct {
|
||||
ChainConfig
|
||||
Apis []string
|
||||
CustomHeader map[string]string
|
||||
Threshold int
|
||||
NoFilter bool
|
||||
}
|
||||
|
||||
// ChainConfig contains the beacon chain configuration.
|
||||
|
|
@ -121,6 +53,7 @@ type ChainConfig struct {
|
|||
GenesisTime uint64 // Unix timestamp of slot 0
|
||||
GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation
|
||||
Forks Forks
|
||||
Checkpoint common.Hash
|
||||
}
|
||||
|
||||
// ForkAtEpoch returns the latest active fork at the given epoch.
|
||||
|
|
@ -202,3 +135,79 @@ func (c *ChainConfig) LoadForks(path string) error {
|
|||
}
|
||||
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})
|
||||
)
|
||||
|
|
@ -70,7 +70,7 @@ func main() {
|
|||
|
||||
func sync(ctx *cli.Context) error {
|
||||
// set up blsync
|
||||
client := blsync.NewClient(ctx)
|
||||
client := blsync.NewClient(utils.MakeBeaconLightConfig(ctx))
|
||||
client.SetEngineRPC(makeRPCClient(ctx))
|
||||
client.Start()
|
||||
|
||||
|
|
|
|||
|
|
@ -76,36 +76,53 @@ func readGenesis(genesisPath string) *core.Genesis {
|
|||
}
|
||||
|
||||
type execStats struct {
|
||||
time time.Duration // The execution time.
|
||||
allocs int64 // The number of heap allocations during execution.
|
||||
bytesAllocated int64 // The cumulative number of bytes allocated during execution.
|
||||
Time time.Duration `json:"time"` // The execution Time.
|
||||
Allocs int64 `json:"allocs"` // The number of heap allocations 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 {
|
||||
// Do one warm-up run
|
||||
output, gasUsed, err := execFunc()
|
||||
result := testing.Benchmark(func(b *testing.B) {
|
||||
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.
|
||||
// There are other useful stats here that could be reported.
|
||||
stats.time = time.Duration(result.NsPerOp())
|
||||
stats.allocs = result.AllocsPerOp()
|
||||
stats.bytesAllocated = result.AllocedBytesPerOp()
|
||||
} else {
|
||||
var memStatsBefore, memStatsAfter goruntime.MemStats
|
||||
goruntime.ReadMemStats(&memStatsBefore)
|
||||
startTime := time.Now()
|
||||
output, gasLeft, err = execFunc()
|
||||
stats.time = time.Since(startTime)
|
||||
goruntime.ReadMemStats(&memStatsAfter)
|
||||
stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
|
||||
stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc)
|
||||
stats := execStats{
|
||||
Time: time.Duration(result.NsPerOp()),
|
||||
Allocs: result.AllocsPerOp(),
|
||||
BytesAllocated: result.AllocedBytesPerOp(),
|
||||
GasUsed: gasUsed,
|
||||
}
|
||||
return output, stats, err
|
||||
}
|
||||
|
||||
return output, gasLeft, stats, err
|
||||
var memStatsBefore, memStatsAfter goruntime.MemStats
|
||||
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 {
|
||||
|
|
@ -265,12 +282,13 @@ func runCmd(ctx *cli.Context) error {
|
|||
statedb.SetCode(receiver, code)
|
||||
}
|
||||
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)
|
||||
output, leftOverGas, stats, err := timedExec(bench, execFunc)
|
||||
output, stats, err := timedExec(bench, execFunc)
|
||||
|
||||
if ctx.Bool(DumpFlag.Name) {
|
||||
root, err := statedb.Commit(genesisConfig.Number, true)
|
||||
|
|
@ -300,7 +318,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
execution time: %v
|
||||
allocations: %d
|
||||
allocated bytes: %d
|
||||
`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated)
|
||||
`, stats.GasUsed, stats.Time, stats.Allocs, stats.BytesAllocated)
|
||||
}
|
||||
if tracer == nil {
|
||||
fmt.Printf("%#x\n", output)
|
||||
|
|
|
|||
|
|
@ -27,26 +27,51 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
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{
|
||||
Action: stateTestCmd,
|
||||
Name: "statetest",
|
||||
Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
|
||||
ArgsUsage: "<file>",
|
||||
Flags: []cli.Flag{
|
||||
forkFlag,
|
||||
idxFlag,
|
||||
testNameFlag,
|
||||
},
|
||||
}
|
||||
|
||||
// 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.
|
||||
type StatetestResult struct {
|
||||
Name string `json:"name"`
|
||||
Pass bool `json:"pass"`
|
||||
Root *common.Hash `json:"stateRoot,omitempty"`
|
||||
Fork string `json:"fork"`
|
||||
Error string `json:"error,omitempty"`
|
||||
State *state.Dump `json:"state,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Pass bool `json:"pass"`
|
||||
Root *common.Hash `json:"stateRoot,omitempty"`
|
||||
Fork string `json:"fork"`
|
||||
Error string `json:"error,omitempty"`
|
||||
State *state.Dump `json:"state,omitempty"`
|
||||
BenchStats *execStats `json:"benchStats,omitempty"`
|
||||
}
|
||||
|
||||
func stateTestCmd(ctx *cli.Context) error {
|
||||
|
|
@ -67,7 +92,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
}
|
||||
// Load the test content from the input file
|
||||
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
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
|
@ -76,15 +101,48 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
if len(fname) == 0 {
|
||||
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 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.
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -94,31 +152,38 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
matchingTests := collectMatchedSubtests(ctx, testsByName)
|
||||
|
||||
// Iterate over all the tests, run them and aggregate the results
|
||||
results := make([]StatetestResult, 0, len(testsByName))
|
||||
for key, test := range testsByName {
|
||||
for _, st := range test.Subtests() {
|
||||
// Run the test and aggregate the result
|
||||
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
||||
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
|
||||
var root common.Hash
|
||||
if tstate.StateDB != nil {
|
||||
root = tstate.StateDB.IntermediateRoot(false)
|
||||
result.Root = &root
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
if dump { // Dump any state to aid debugging
|
||||
cpy, _ := state.New(root, tstate.StateDB.Database())
|
||||
dump := cpy.RawDump(nil)
|
||||
result.State = &dump
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// Test failed, mark as so
|
||||
result.Pass, result.Error = false, err.Error()
|
||||
var results []StatetestResult
|
||||
for _, test := range matchingTests {
|
||||
// Run the test and aggregate the result
|
||||
result := &StatetestResult{Name: test.name, Fork: test.st.Fork, Pass: true}
|
||||
test.test.Run(test.st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
|
||||
var root common.Hash
|
||||
if tstate.StateDB != nil {
|
||||
root = tstate.StateDB.IntermediateRoot(false)
|
||||
result.Root = &root
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
if dump { // Dump any state to aid debugging
|
||||
cpy, _ := state.New(root, tstate.StateDB.Database())
|
||||
dump := cpy.RawDump(nil)
|
||||
result.State = &dump
|
||||
}
|
||||
}
|
||||
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, "", " ")
|
||||
fmt.Println(string(out))
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
|||
// Start blsync mode.
|
||||
srv := rpc.NewServer()
|
||||
srv.RegisterName("engine", catalyst.NewConsensusAPI(eth))
|
||||
blsyncer := blsync.NewClient(ctx)
|
||||
blsyncer := blsync.NewClient(utils.MakeBeaconLightConfig(ctx))
|
||||
blsyncer.SetEngineRPC(rpc.DialInProc(srv))
|
||||
stack.RegisterLifecycle(blsyncer)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import (
|
|||
bparams "github.com/ethereum/go-ethereum/beacon/params"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||
|
|
@ -1970,6 +1971,81 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// no URLs are set.
|
||||
func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
||||
|
|
|
|||
|
|
@ -186,9 +186,9 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
|||
// is optional and may be partially useful if it's not fully
|
||||
// generated.
|
||||
if db.snap != nil {
|
||||
sr, err := newStateReader(stateRoot, db.snap)
|
||||
if err == nil {
|
||||
readers = append(readers, sr) // snap reader is optional
|
||||
snap := db.snap.Snapshot(stateRoot)
|
||||
if snap != nil {
|
||||
readers = append(readers, newStateReader(snap)) // snap reader is optional
|
||||
}
|
||||
}
|
||||
// Set up the trie reader, which is expected to always be available
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ import (
|
|||
"maps"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/utils"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
)
|
||||
|
||||
// Reader defines the interface for accessing accounts and storage slots
|
||||
|
|
@ -52,23 +52,18 @@ type Reader interface {
|
|||
Copy() Reader
|
||||
}
|
||||
|
||||
// stateReader is a wrapper over the state snapshot and implements the Reader
|
||||
// interface. It provides an efficient way to access flat state.
|
||||
// stateReader wraps a database state reader.
|
||||
type stateReader struct {
|
||||
snap snapshot.Snapshot
|
||||
buff crypto.KeccakState
|
||||
reader database.StateReader
|
||||
buff crypto.KeccakState
|
||||
}
|
||||
|
||||
// newStateReader constructs a flat state reader with on the specified state root.
|
||||
func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) {
|
||||
snap := snaps.Snapshot(root)
|
||||
if snap == nil {
|
||||
return nil, errors.New("snapshot is not available")
|
||||
}
|
||||
// newStateReader constructs a state reader with on the given state root.
|
||||
func newStateReader(reader database.StateReader) *stateReader {
|
||||
return &stateReader{
|
||||
snap: snap,
|
||||
buff: crypto.NewKeccakState(),
|
||||
}, nil
|
||||
reader: reader,
|
||||
buff: crypto.NewKeccakState(),
|
||||
}
|
||||
}
|
||||
|
||||
// Account implements Reader, retrieving the account specified by the address.
|
||||
|
|
@ -78,18 +73,18 @@ func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error
|
|||
//
|
||||
// The returned account might be nil if it's not existent.
|
||||
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||
ret, err := r.snap.Account(crypto.HashData(r.buff, addr.Bytes()))
|
||||
account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret == nil {
|
||||
if account == nil {
|
||||
return nil, nil
|
||||
}
|
||||
acct := &types.StateAccount{
|
||||
Nonce: ret.Nonce,
|
||||
Balance: ret.Balance,
|
||||
CodeHash: ret.CodeHash,
|
||||
Root: common.BytesToHash(ret.Root),
|
||||
Nonce: account.Nonce,
|
||||
Balance: account.Balance,
|
||||
CodeHash: account.CodeHash,
|
||||
Root: common.BytesToHash(account.Root),
|
||||
}
|
||||
if len(acct.CodeHash) == 0 {
|
||||
acct.CodeHash = types.EmptyCodeHash.Bytes()
|
||||
|
|
@ -110,7 +105,7 @@ func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error)
|
|||
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||
addrHash := crypto.HashData(r.buff, addr.Bytes())
|
||||
slotHash := crypto.HashData(r.buff, key.Bytes())
|
||||
ret, err := r.snap.Storage(addrHash, slotHash)
|
||||
ret, err := r.reader.Storage(addrHash, slotHash)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
|
@ -131,8 +126,8 @@ func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash
|
|||
// Copy implements Reader, returning a deep-copied snap reader.
|
||||
func (r *stateReader) Copy() Reader {
|
||||
return &stateReader{
|
||||
snap: r.snap,
|
||||
buff: crypto.NewKeccakState(),
|
||||
reader: r.reader,
|
||||
buff: crypto.NewKeccakState(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,22 +198,46 @@ func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value
|
|||
}
|
||||
|
||||
func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int {
|
||||
prev := s.inner.SelfDestruct(address)
|
||||
if !prev.IsZero() {
|
||||
if s.hooks.OnBalanceChange != nil {
|
||||
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||
}
|
||||
var prevCode []byte
|
||||
var prevCodeHash common.Hash
|
||||
|
||||
if s.hooks.OnCodeChange != nil {
|
||||
prevCode = s.inner.GetCode(address)
|
||||
prevCodeHash = s.inner.GetCodeHash(address)
|
||||
}
|
||||
|
||||
prev := s.inner.SelfDestruct(address)
|
||||
|
||||
if s.hooks.OnBalanceChange != nil && !prev.IsZero() {
|
||||
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||
}
|
||||
|
||||
if s.hooks.OnCodeChange != nil && len(prevCode) > 0 {
|
||||
s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
|
||||
}
|
||||
|
||||
return prev
|
||||
}
|
||||
|
||||
func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) {
|
||||
prev, changed := s.inner.SelfDestruct6780(address)
|
||||
if !prev.IsZero() && changed {
|
||||
if s.hooks.OnBalanceChange != nil {
|
||||
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||
}
|
||||
var prevCode []byte
|
||||
var prevCodeHash common.Hash
|
||||
|
||||
if s.hooks.OnCodeChange != nil {
|
||||
prevCodeHash = s.inner.GetCodeHash(address)
|
||||
prevCode = s.inner.GetCode(address)
|
||||
}
|
||||
|
||||
prev, changed := s.inner.SelfDestruct6780(address)
|
||||
|
||||
if s.hooks.OnBalanceChange != nil && changed && !prev.IsZero() {
|
||||
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||
}
|
||||
|
||||
if s.hooks.OnCodeChange != nil && changed && len(prevCode) > 0 {
|
||||
s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
|
||||
}
|
||||
|
||||
return prev, changed
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
|
|
@ -37,6 +39,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -142,10 +145,12 @@ func (b *testBackend) RunPeer(peer *Peer, handler Handler) error {
|
|||
func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") }
|
||||
|
||||
func (b *testBackend) AcceptTxs() bool {
|
||||
panic("data processing tests should be done in the handler package")
|
||||
return true
|
||||
//panic("data processing tests should be done in the handler package")
|
||||
}
|
||||
func (b *testBackend) Handle(*Peer, Packet) error {
|
||||
panic("data processing tests should be done in the handler package")
|
||||
return nil
|
||||
//panic("data processing tests should be done in the handler package")
|
||||
}
|
||||
|
||||
// Tests that block headers can be retrieved from a remote chain based on user queries.
|
||||
|
|
@ -498,3 +503,76 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
|
|||
t.Errorf("receipts mismatch: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type decoder struct {
|
||||
msg []byte
|
||||
}
|
||||
|
||||
func (d decoder) Decode(val interface{}) error {
|
||||
buffer := bytes.NewBuffer(d.msg)
|
||||
s := rlp.NewStream(buffer, uint64(len(d.msg)))
|
||||
return s.Decode(val)
|
||||
}
|
||||
|
||||
func (d decoder) Time() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func setup() (*testBackend, *testPeer) {
|
||||
// Generate some transactions etc.
|
||||
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
|
||||
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
|
||||
signer := types.HomesteadSigner{}
|
||||
gen := func(n int, block *core.BlockGen) {
|
||||
if n%2 == 0 {
|
||||
w := &types.Withdrawal{
|
||||
Address: common.Address{0xaa},
|
||||
Amount: 42,
|
||||
}
|
||||
block.AddWithdrawal(w)
|
||||
}
|
||||
switch n {
|
||||
case 0:
|
||||
// In block 1, the test bank sends account #1 some ether.
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
|
||||
block.AddTx(tx)
|
||||
case 1:
|
||||
// In block 2, the test bank sends some more ether to account #1.
|
||||
// acc1Addr passes it on to account #2.
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
|
||||
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key)
|
||||
block.AddTx(tx1)
|
||||
block.AddTx(tx2)
|
||||
case 2:
|
||||
// Block 3 is empty but was mined by account #2.
|
||||
block.SetCoinbase(acc2Addr)
|
||||
block.SetExtra([]byte("yeehaw"))
|
||||
}
|
||||
}
|
||||
backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen)
|
||||
peer, _ := newTestPeer("peer", ETH68, backend)
|
||||
// Discard all messages
|
||||
go func() {
|
||||
for {
|
||||
msg, err := peer.app.ReadMsg()
|
||||
if err == nil {
|
||||
msg.Discard()
|
||||
}
|
||||
}
|
||||
}()
|
||||
return backend, peer
|
||||
}
|
||||
|
||||
func FuzzEthProtocolHandlers(f *testing.F) {
|
||||
handlers := eth68
|
||||
backend, peer := setup()
|
||||
f.Fuzz(func(t *testing.T, code byte, msg []byte) {
|
||||
handler := handlers[uint64(code)%protocolLengths[ETH68]]
|
||||
if handler == nil {
|
||||
return
|
||||
}
|
||||
handler(backend, decoder{msg: msg}, peer.Peer)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
|
|
@ -164,55 +165,85 @@ func TestGethClient(t *testing.T) {
|
|||
|
||||
func testAccessList(t *testing.T, client *rpc.Client) {
|
||||
ec := New(client)
|
||||
// Test transfer
|
||||
msg := ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: &common.Address{},
|
||||
Gas: 21000,
|
||||
GasPrice: big.NewInt(875000000),
|
||||
Value: big.NewInt(1),
|
||||
}
|
||||
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if vmErr != "" {
|
||||
t.Fatalf("unexpected vm error: %v", vmErr)
|
||||
}
|
||||
if gas != 21000 {
|
||||
t.Fatalf("unexpected gas used: %v", gas)
|
||||
}
|
||||
if len(*al) != 0 {
|
||||
t.Fatalf("unexpected length of accesslist: %v", len(*al))
|
||||
}
|
||||
// Test reverting transaction
|
||||
msg = ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: nil,
|
||||
Gas: 100000,
|
||||
GasPrice: big.NewInt(1000000000),
|
||||
Value: big.NewInt(1),
|
||||
Data: common.FromHex("0x608060806080608155fd"),
|
||||
}
|
||||
al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if vmErr == "" {
|
||||
t.Fatalf("wanted vmErr, got none")
|
||||
}
|
||||
if gas == 21000 {
|
||||
t.Fatalf("unexpected gas used: %v", gas)
|
||||
}
|
||||
if len(*al) != 1 || al.StorageKeys() != 1 {
|
||||
t.Fatalf("unexpected length of accesslist: %v", len(*al))
|
||||
}
|
||||
// address changes between calls, so we can't test for it.
|
||||
if (*al)[0].Address == common.HexToAddress("0x0") {
|
||||
t.Fatalf("unexpected address: %v", (*al)[0].Address)
|
||||
}
|
||||
if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") {
|
||||
t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0])
|
||||
|
||||
for i, tc := range []struct {
|
||||
msg ethereum.CallMsg
|
||||
wantGas uint64
|
||||
wantErr string
|
||||
wantVMErr string
|
||||
wantAL string
|
||||
}{
|
||||
{ // Test transfer
|
||||
msg: ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: &common.Address{},
|
||||
Gas: 21000,
|
||||
GasPrice: big.NewInt(875000000),
|
||||
Value: big.NewInt(1),
|
||||
},
|
||||
wantGas: 21000,
|
||||
wantAL: `[]`,
|
||||
},
|
||||
{ // Test reverting transaction
|
||||
msg: ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: nil,
|
||||
Gas: 100000,
|
||||
GasPrice: big.NewInt(1000000000),
|
||||
Value: big.NewInt(1),
|
||||
Data: common.FromHex("0x608060806080608155fd"),
|
||||
},
|
||||
wantGas: 77496,
|
||||
wantVMErr: "execution reverted",
|
||||
wantAL: `[
|
||||
{
|
||||
"address": "0x3a220f351252089d385b29beca14e27f204c296a",
|
||||
"storageKeys": [
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000081"
|
||||
]
|
||||
}
|
||||
]`,
|
||||
},
|
||||
{ // error when gasPrice is less than baseFee
|
||||
msg: ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: &common.Address{},
|
||||
Gas: 21000,
|
||||
GasPrice: big.NewInt(1), // less than baseFee
|
||||
Value: big.NewInt(1),
|
||||
},
|
||||
wantErr: "max fee per gas less than block base fee",
|
||||
},
|
||||
{ // when gasPrice is not specified
|
||||
msg: ethereum.CallMsg{
|
||||
From: testAddr,
|
||||
To: &common.Address{},
|
||||
Gas: 21000,
|
||||
Value: big.NewInt(1),
|
||||
},
|
||||
wantGas: 21000,
|
||||
wantAL: `[]`,
|
||||
},
|
||||
} {
|
||||
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), tc.msg)
|
||||
if tc.wantErr != "" {
|
||||
if !strings.Contains(err.Error(), tc.wantErr) {
|
||||
t.Fatalf("test %d: wrong error: %v", i, err)
|
||||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
t.Fatalf("test %d: wrong error: %v", i, err)
|
||||
}
|
||||
if have, want := vmErr, tc.wantVMErr; have != want {
|
||||
t.Fatalf("test %d: vmErr wrong, have %v want %v", i, have, want)
|
||||
}
|
||||
if have, want := gas, tc.wantGas; have != want {
|
||||
t.Fatalf("test %d: gas wrong, have %v want %v", i, have, want)
|
||||
}
|
||||
haveList, _ := json.MarshalIndent(al, "", " ")
|
||||
if have, want := string(haveList), tc.wantAL; have != want {
|
||||
t.Fatalf("test %d: access list wrong, have:\n%v\nwant:\n%v", i, have, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1287,9 +1287,18 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||
}
|
||||
|
||||
// Ensure any missing fields are filled, extract the recipient and input data
|
||||
if err := args.setDefaults(ctx, b, true); err != nil {
|
||||
if err = args.setFeeDefaults(ctx, b, header); err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
if args.Nonce == nil {
|
||||
nonce := hexutil.Uint64(db.GetNonce(args.from()))
|
||||
args.Nonce = &nonce
|
||||
}
|
||||
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
|
||||
if err = args.CallDefaults(b.RPCGasCap(), blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
|
||||
var to common.Address
|
||||
if args.To != nil {
|
||||
to = *args.To
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas
|
|||
if err := args.setBlobTxSidecar(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := args.setFeeDefaults(ctx, b); err != nil {
|
||||
if err := args.setFeeDefaults(ctx, b, b.CurrentHeader()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -183,8 +183,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas
|
|||
}
|
||||
|
||||
// setFeeDefaults fills in default fee values for unspecified tx fields.
|
||||
func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) error {
|
||||
head := b.CurrentHeader()
|
||||
func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend, head *types.Header) error {
|
||||
// Sanity check the EIP-4844 fee parameters.
|
||||
if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
|
||||
return errors.New("maxFeePerBlobGas, if specified, must be non-zero")
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ func TestSetFeeDefaults(t *testing.T) {
|
|||
t.Fatalf("failed to set fork: %v", err)
|
||||
}
|
||||
got := test.in
|
||||
err := got.setFeeDefaults(ctx, b)
|
||||
err := got.setFeeDefaults(ctx, b, b.CurrentHeader())
|
||||
if err != nil {
|
||||
if test.err == nil {
|
||||
t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
|
||||
|
|
|
|||
|
|
@ -220,6 +220,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
|
|||
Fuzz fuzzSecp256k1\
|
||||
$repo/tests/fuzzers/secp256k1/secp_test.go
|
||||
|
||||
compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \
|
||||
FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \
|
||||
$repo/eth/protocols/eth/handler_test.go
|
||||
|
||||
|
||||
#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
|
||||
#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty
|
||||
|
|
|
|||
|
|
@ -18,12 +18,18 @@ package apitypes
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"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/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBytesPadding(t *testing.T) {
|
||||
|
|
@ -244,45 +250,42 @@ func TestConvertAddressDataToSlice(t *testing.T) {
|
|||
func TestTypedDataArrayValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
typedData := TypedData{
|
||||
Types: Types{
|
||||
"BulkOrder": []Type{
|
||||
// Should be able to accept fixed size arrays
|
||||
{Name: "tree", Type: "OrderComponents[2][2]"},
|
||||
},
|
||||
"OrderComponents": []Type{
|
||||
{Name: "offerer", Type: "address"},
|
||||
{Name: "amount", Type: "uint8"},
|
||||
},
|
||||
"EIP712Domain": []Type{
|
||||
{Name: "name", Type: "string"},
|
||||
{Name: "version", Type: "string"},
|
||||
{Name: "chainId", Type: "uint8"},
|
||||
{Name: "verifyingContract", Type: "address"},
|
||||
},
|
||||
},
|
||||
PrimaryType: "BulkOrder",
|
||||
Domain: TypedDataDomain{
|
||||
VerifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
|
||||
},
|
||||
Message: TypedDataMessage{},
|
||||
type testDataInput struct {
|
||||
Name string `json:"name"`
|
||||
Domain TypedDataDomain `json:"domain"`
|
||||
PrimaryType string `json:"primaryType"`
|
||||
Types Types `json:"types"`
|
||||
Message TypedDataMessage `json:"data"`
|
||||
Digest string `json:"digest"`
|
||||
}
|
||||
fc, err := os.ReadFile("./testdata/typed-data.json")
|
||||
require.NoError(t, err, "error reading test data file")
|
||||
|
||||
if err := typedData.validate(); err != nil {
|
||||
t.Errorf("expected typed data to pass validation, got: %v", err)
|
||||
}
|
||||
var tests []testDataInput
|
||||
err = json.Unmarshal(fc, &tests)
|
||||
require.NoError(t, err, "error unmarshalling test data file contents")
|
||||
|
||||
// Should be able to accept dynamic arrays
|
||||
typedData.Types["BulkOrder"][0].Type = "OrderComponents[]"
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if err := typedData.validate(); err != nil {
|
||||
t.Errorf("expected typed data to pass validation, got: %v", err)
|
||||
}
|
||||
td := TypedData{
|
||||
Types: tc.Types,
|
||||
PrimaryType: tc.PrimaryType,
|
||||
Domain: tc.Domain,
|
||||
Message: tc.Message,
|
||||
}
|
||||
|
||||
// Should be able to accept standard types
|
||||
typedData.Types["BulkOrder"][0].Type = "OrderComponents"
|
||||
domainSeparator, tErr := td.HashStruct("EIP712Domain", td.Domain.Map())
|
||||
assert.NoError(t, tErr, "failed to hash domain separator: %v", tErr)
|
||||
|
||||
if err := typedData.validate(); err != nil {
|
||||
t.Errorf("expected typed data to pass validation, got: %v", err)
|
||||
messageHash, tErr := td.HashStruct(td.PrimaryType, td.Message)
|
||||
assert.NoError(t, tErr, "failed to hash message: %v", tErr)
|
||||
|
||||
digest := crypto.Keccak256Hash([]byte(fmt.Sprintf("%s%s%s", "\x19\x01", string(domainSeparator), string(messageHash))))
|
||||
assert.Equal(t, tc.Digest, digest.String(), "digest doesn't not match")
|
||||
|
||||
assert.NoError(t, td.validate(), "validation failed", tErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6089
signer/core/apitypes/testdata/typed-data.json
vendored
Normal file
6089
signer/core/apitypes/testdata/typed-data.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -325,18 +325,17 @@ type Type struct {
|
|||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// isArray returns true if the type is a fixed or variable sized array.
|
||||
// This method may return false positives, in case the Type is not a valid
|
||||
// expression, e.g. "fooo[[[[".
|
||||
func (t *Type) isArray() bool {
|
||||
return strings.HasSuffix(t.Type, "[]")
|
||||
return strings.IndexByte(t.Type, '[') > 0
|
||||
}
|
||||
|
||||
// typeName returns the canonical name of the type. If the type is 'Person[]', then
|
||||
// typeName returns the canonical name of the type. If the type is 'Person[]' or 'Person[2]', then
|
||||
// this method returns 'Person'
|
||||
func (t *Type) typeName() string {
|
||||
if strings.Contains(t.Type, "[") {
|
||||
re := regexp.MustCompile(`\[\d*\]`)
|
||||
return re.ReplaceAllString(t.Type, "")
|
||||
}
|
||||
return t.Type
|
||||
return strings.Split(t.Type, "[")[0]
|
||||
}
|
||||
|
||||
type Types map[string][]Type
|
||||
|
|
@ -387,7 +386,7 @@ func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage
|
|||
|
||||
// Dependencies returns an array of custom types ordered by their hierarchical reference tree
|
||||
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string {
|
||||
primaryType = strings.TrimSuffix(primaryType, "[]")
|
||||
primaryType = strings.Split(primaryType, "[")[0]
|
||||
|
||||
if slices.Contains(found, primaryType) {
|
||||
return found
|
||||
|
|
@ -465,34 +464,11 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
|
|||
encType := field.Type
|
||||
encValue := data[field.Name]
|
||||
if encType[len(encType)-1:] == "]" {
|
||||
arrayValue, err := convertDataToSlice(encValue)
|
||||
encodedData, err := typedData.encodeArrayValue(encValue, encType, depth)
|
||||
if err != nil {
|
||||
return nil, dataMismatchError(encType, encValue)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
arrayBuffer := bytes.Buffer{}
|
||||
parsedType := strings.Split(encType, "[")[0]
|
||||
for _, item := range arrayValue {
|
||||
if typedData.Types[parsedType] != nil {
|
||||
mapValue, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, dataMismatchError(parsedType, item)
|
||||
}
|
||||
encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arrayBuffer.Write(crypto.Keccak256(encodedData))
|
||||
} else {
|
||||
bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arrayBuffer.Write(bytesValue)
|
||||
}
|
||||
}
|
||||
|
||||
buffer.Write(crypto.Keccak256(arrayBuffer.Bytes()))
|
||||
buffer.Write(encodedData)
|
||||
} else if typedData.Types[field.Type] != nil {
|
||||
mapValue, ok := encValue.(map[string]interface{})
|
||||
if !ok {
|
||||
|
|
@ -514,6 +490,46 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
|
|||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func (typedData *TypedData) encodeArrayValue(encValue interface{}, encType string, depth int) (hexutil.Bytes, error) {
|
||||
arrayValue, err := convertDataToSlice(encValue)
|
||||
if err != nil {
|
||||
return nil, dataMismatchError(encType, encValue)
|
||||
}
|
||||
|
||||
arrayBuffer := new(bytes.Buffer)
|
||||
parsedType := strings.Split(encType, "[")[0]
|
||||
for _, item := range arrayValue {
|
||||
if reflect.TypeOf(item).Kind() == reflect.Slice ||
|
||||
reflect.TypeOf(item).Kind() == reflect.Array {
|
||||
encodedData, err := typedData.encodeArrayValue(item, parsedType, depth+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arrayBuffer.Write(encodedData)
|
||||
} else {
|
||||
if typedData.Types[parsedType] != nil {
|
||||
mapValue, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, dataMismatchError(parsedType, item)
|
||||
}
|
||||
encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest := crypto.Keccak256(encodedData)
|
||||
arrayBuffer.Write(digest)
|
||||
} else {
|
||||
bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arrayBuffer.Write(bytesValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
return crypto.Keccak256(arrayBuffer.Bytes()), nil
|
||||
}
|
||||
|
||||
// Attempt to parse bytes in different formats: byte array, hex string, hexutil.Bytes.
|
||||
func parseBytes(encType interface{}) ([]byte, bool) {
|
||||
// Handle array types.
|
||||
|
|
@ -871,7 +887,8 @@ func init() {
|
|||
|
||||
// Checks if the primitive value is valid
|
||||
func isPrimitiveTypeValid(primitiveType string) bool {
|
||||
_, ok := validPrimitiveTypes[primitiveType]
|
||||
input := strings.Split(primitiveType, "[")[0]
|
||||
_, ok := validPrimitiveTypes[input]
|
||||
return ok
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ func TestIsPrimitive(t *testing.T) {
|
|||
t.Parallel()
|
||||
// Expected positives
|
||||
for i, tc := range []string{
|
||||
"int24", "int24[]", "uint88", "uint88[]", "uint", "uint[]", "int256", "int256[]",
|
||||
"uint96", "uint96[]", "int96", "int96[]", "bytes17[]", "bytes17",
|
||||
"int24", "int24[]", "int[]", "int[2]", "uint88", "uint88[]", "uint", "uint[]", "uint[2]", "int256", "int256[]",
|
||||
"uint96", "uint96[]", "int96", "int96[]", "bytes17[]", "bytes17", "address[2]", "bool[4]", "string[5]", "bytes[2]",
|
||||
"bytes32", "bytes32[]", "bytes32[4]",
|
||||
} {
|
||||
if !isPrimitiveTypeValid(tc) {
|
||||
t.Errorf("test %d: expected '%v' to be a valid primitive", i, tc)
|
||||
|
|
@ -141,3 +142,94 @@ func TestBlobTxs(t *testing.T) {
|
|||
}
|
||||
t.Logf("tx %v", string(data))
|
||||
}
|
||||
|
||||
func TestType_IsArray(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Expected positives
|
||||
for i, tc := range []Type{
|
||||
{
|
||||
Name: "type1",
|
||||
Type: "int24[]",
|
||||
},
|
||||
{
|
||||
Name: "type2",
|
||||
Type: "int24[2]",
|
||||
},
|
||||
{
|
||||
Name: "type3",
|
||||
Type: "int24[2][2][2]",
|
||||
},
|
||||
} {
|
||||
if !tc.isArray() {
|
||||
t.Errorf("test %d: expected '%v' to be an array", i, tc)
|
||||
}
|
||||
}
|
||||
// Expected negatives
|
||||
for i, tc := range []Type{
|
||||
{
|
||||
Name: "type1",
|
||||
Type: "int24",
|
||||
},
|
||||
{
|
||||
Name: "type2",
|
||||
Type: "uint88",
|
||||
},
|
||||
{
|
||||
Name: "type3",
|
||||
Type: "bytes32",
|
||||
},
|
||||
} {
|
||||
if tc.isArray() {
|
||||
t.Errorf("test %d: expected '%v' to not be an array", i, tc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestType_TypeName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for i, tc := range []struct {
|
||||
Input Type
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
Input: Type{
|
||||
Name: "type1",
|
||||
Type: "int24[]",
|
||||
},
|
||||
Expected: "int24",
|
||||
},
|
||||
{
|
||||
Input: Type{
|
||||
Name: "type2",
|
||||
Type: "int26[2][2][2]",
|
||||
},
|
||||
Expected: "int26",
|
||||
},
|
||||
{
|
||||
Input: Type{
|
||||
Name: "type3",
|
||||
Type: "int24",
|
||||
},
|
||||
Expected: "int24",
|
||||
},
|
||||
{
|
||||
Input: Type{
|
||||
Name: "type4",
|
||||
Type: "uint88",
|
||||
},
|
||||
Expected: "uint88",
|
||||
},
|
||||
{
|
||||
Input: Type{
|
||||
Name: "type5",
|
||||
Type: "bytes32[2]",
|
||||
},
|
||||
Expected: "bytes32",
|
||||
},
|
||||
} {
|
||||
if tc.Input.typeName() != tc.Expected {
|
||||
t.Errorf("test %d: expected typeName value of '%v' but got '%v'", i, tc.Expected, tc.Input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error {
|
|||
|
||||
// Run executes a specific subtest and verifies the post-state and logs
|
||||
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) {
|
||||
st, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
|
||||
st, root, _, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
|
||||
// Invoke the callback at the end of function for further analysis.
|
||||
defer func() {
|
||||
postCheck(result, &st)
|
||||
|
|
@ -228,10 +228,10 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
|
|||
|
||||
// RunNoVerify runs a specific subtest and returns the statedb and post-state root.
|
||||
// Remember to call state.Close after verifying the test result!
|
||||
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, err error) {
|
||||
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, gasUsed uint64, err error) {
|
||||
config, eips, err := GetChainConfig(subtest.Fork)
|
||||
if err != nil {
|
||||
return st, common.Hash{}, UnsupportedForkError{subtest.Fork}
|
||||
return st, common.Hash{}, 0, UnsupportedForkError{subtest.Fork}
|
||||
}
|
||||
vmconfig.ExtraEips = eips
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
post := t.json.Post[subtest.Fork][subtest.Index]
|
||||
msg, err := t.json.Tx.toMessage(post, baseFee)
|
||||
if err != nil {
|
||||
return st, common.Hash{}, err
|
||||
return st, common.Hash{}, 0, err
|
||||
}
|
||||
|
||||
{ // Blob transactions may be present after the Cancun fork.
|
||||
|
|
@ -260,7 +260,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
// Here, we just do this shortcut smaller fix, since state tests do not
|
||||
// utilize those codepaths
|
||||
if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
|
||||
return st, common.Hash{}, errors.New("blob gas exceeds maximum")
|
||||
return st, common.Hash{}, 0, errors.New("blob gas exceeds maximum")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -269,10 +269,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
var ttx types.Transaction
|
||||
err := ttx.UnmarshalBinary(post.TxBytes)
|
||||
if err != nil {
|
||||
return st, common.Hash{}, err
|
||||
return st, common.Hash{}, 0, err
|
||||
}
|
||||
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
|
||||
return st, common.Hash{}, err
|
||||
return st, common.Hash{}, 0, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
receipt := &types.Receipt{GasUsed: vmRet.UsedGas}
|
||||
tracer.OnTxEnd(receipt, nil)
|
||||
}
|
||||
return st, root, err
|
||||
return st, root, vmRet.UsedGas, err
|
||||
}
|
||||
|
||||
func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
|
||||
|
|
|
|||
|
|
@ -156,10 +156,6 @@ func GetTreeKey(address []byte, treeIndex *uint256.Int, subIndex byte) []byte {
|
|||
func GetTreeKeyWithEvaluatedAddress(evaluated *verkle.Point, treeIndex *uint256.Int, subIndex byte) []byte {
|
||||
var poly [5]fr.Element
|
||||
|
||||
poly[0].SetZero()
|
||||
poly[1].SetZero()
|
||||
poly[2].SetZero()
|
||||
|
||||
// little-endian, 32-byte aligned treeIndex
|
||||
var index [32]byte
|
||||
for i := 0; i < len(treeIndex); i++ {
|
||||
|
|
@ -297,8 +293,6 @@ func evaluateAddressPoint(address []byte) *verkle.Point {
|
|||
}
|
||||
var poly [3]fr.Element
|
||||
|
||||
poly[0].SetZero()
|
||||
|
||||
// 32-byte address, interpreted as two little endian
|
||||
// 16-byte numbers.
|
||||
verkle.FromLEBytes(&poly[1], address[:16])
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package database
|
|||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// NodeReader wraps the Node method of a backing trie reader.
|
||||
|
|
@ -37,3 +38,31 @@ type NodeDatabase interface {
|
|||
// An error will be returned if the specified state is not available.
|
||||
NodeReader(stateRoot common.Hash) (NodeReader, error)
|
||||
}
|
||||
|
||||
// StateReader wraps the Account and Storage method of a backing state reader.
|
||||
type StateReader interface {
|
||||
// Account directly retrieves the account associated with a particular hash in
|
||||
// the slim data format. An error will be returned if the read operation exits
|
||||
// abnormally. Specifically, if the layer is already stale.
|
||||
//
|
||||
// Note:
|
||||
// - the returned account object is safe to modify
|
||||
// - no error will be returned if the requested account is not found in database
|
||||
Account(hash common.Hash) (*types.SlimAccount, error)
|
||||
|
||||
// Storage directly retrieves the storage data associated with a particular hash,
|
||||
// within a particular account. An error will be returned if the read operation
|
||||
// exits abnormally.
|
||||
//
|
||||
// Note:
|
||||
// - the returned storage data is not a copy, please don't modify it
|
||||
// - no error will be returned if the requested slot is not found in database
|
||||
Storage(accountHash, storageHash common.Hash) ([]byte, error)
|
||||
}
|
||||
|
||||
// StateDatabase wraps the methods of a backing state store.
|
||||
type StateDatabase interface {
|
||||
// StateReader returns a state reader associated with the specific state.
|
||||
// An error will be returned if the specified state is not available.
|
||||
StateReader(stateRoot common.Hash) (StateReader, error)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue