mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
82a6c3daaf
146 changed files with 2984 additions and 861 deletions
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
|
@ -29,5 +29,5 @@ miner/ @MariusVanDerWijden @fjl @rjl493456442
|
||||||
node/ @fjl
|
node/ @fjl
|
||||||
p2p/ @fjl @zsfelfoldi
|
p2p/ @fjl @zsfelfoldi
|
||||||
rlp/ @fjl
|
rlp/ @fjl
|
||||||
params/ @fjl @karalabe @gballet @rjl493456442 @zsfelfoldi
|
params/ @fjl @gballet @rjl493456442 @zsfelfoldi
|
||||||
rpc/ @fjl
|
rpc/ @fjl
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
intRegex = regexp.MustCompile(`(u)?int([0-9]*)`)
|
||||||
|
)
|
||||||
|
|
||||||
func isKeyWord(arg string) bool {
|
func isKeyWord(arg string) bool {
|
||||||
switch arg {
|
switch arg {
|
||||||
case "break":
|
case "break":
|
||||||
|
|
@ -299,7 +303,7 @@ func bindBasicType(kind abi.Type) string {
|
||||||
case abi.AddressTy:
|
case abi.AddressTy:
|
||||||
return "common.Address"
|
return "common.Address"
|
||||||
case abi.IntTy, abi.UintTy:
|
case abi.IntTy, abi.UintTy:
|
||||||
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
|
parts := intRegex.FindStringSubmatch(kind.String())
|
||||||
switch parts[2] {
|
switch parts[2] {
|
||||||
case "8", "16", "32", "64":
|
case "8", "16", "32", "64":
|
||||||
return fmt.Sprintf("%sint%s", parts[1], parts[2])
|
return fmt.Sprintf("%sint%s", parts[1], parts[2])
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ package bind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
|
@ -241,3 +242,27 @@ func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn {
|
||||||
return addr, tx, nil
|
return addr, tx, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeployerWithNonceAssignment is basically identical to DefaultDeployer,
|
||||||
|
// but it additionally tracks the nonce to enable automatic assignment.
|
||||||
|
//
|
||||||
|
// This is especially useful when deploying multiple contracts
|
||||||
|
// from the same address — whether they are independent contracts
|
||||||
|
// or part of a dependency chain that must be deployed in order.
|
||||||
|
func DeployerWithNonceAssignment(opts *TransactOpts, backend ContractBackend) DeployFn {
|
||||||
|
var pendingNonce int64
|
||||||
|
if opts.Nonce != nil {
|
||||||
|
pendingNonce = opts.Nonce.Int64()
|
||||||
|
}
|
||||||
|
return func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
if pendingNonce != 0 {
|
||||||
|
opts.Nonce = big.NewInt(pendingNonce)
|
||||||
|
}
|
||||||
|
addr, tx, err := DeployContract(opts, deployer, backend, input)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
|
pendingNonce = int64(tx.Nonce() + 1)
|
||||||
|
return addr, tx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,14 @@ func makeTestDeployer(backend simulated.Client) func(input, deployer []byte) (co
|
||||||
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend)
|
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makeTestDeployerWithNonceAssignment is similar to makeTestDeployer,
|
||||||
|
// but it returns a deployer that automatically tracks nonce,
|
||||||
|
// enabling the deployment of multiple contracts from the same account.
|
||||||
|
func makeTestDeployerWithNonceAssignment(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
chainId, _ := backend.ChainID(context.Background())
|
||||||
|
return bind.DeployerWithNonceAssignment(bind.NewKeyedTransactor(testKey, chainId), backend)
|
||||||
|
}
|
||||||
|
|
||||||
// test that deploying a contract with library dependencies works,
|
// test that deploying a contract with library dependencies works,
|
||||||
// verifying by calling method on the deployed contract.
|
// verifying by calling method on the deployed contract.
|
||||||
func TestDeploymentLibraries(t *testing.T) {
|
func TestDeploymentLibraries(t *testing.T) {
|
||||||
|
|
@ -80,7 +88,7 @@ func TestDeploymentLibraries(t *testing.T) {
|
||||||
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
|
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
|
||||||
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
|
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
|
||||||
}
|
}
|
||||||
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend.Client))
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend.Client))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %+v\n", err)
|
t.Fatalf("err: %+v\n", err)
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +130,7 @@ func TestDeploymentWithOverrides(t *testing.T) {
|
||||||
deploymentParams := &bind.DeploymentParams{
|
deploymentParams := &bind.DeploymentParams{
|
||||||
Contracts: nested_libraries.C1MetaData.Deps,
|
Contracts: nested_libraries.C1MetaData.Deps,
|
||||||
}
|
}
|
||||||
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend))
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %+v\n", err)
|
t.Fatalf("err: %+v\n", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
// Package keystore implements encrypted storage of secp256k1 private keys.
|
// Package keystore implements encrypted storage of secp256k1 private keys.
|
||||||
//
|
//
|
||||||
// Keys are stored as encrypted JSON files according to the Web3 Secret Storage specification.
|
// Keys are stored as encrypted JSON files according to the Web3 Secret Storage specification.
|
||||||
// See https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition for more information.
|
// See https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/ for more information.
|
||||||
package keystore
|
package keystore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
This key store behaves as KeyStorePlain with the difference that
|
This key store behaves as KeyStorePlain with the difference that
|
||||||
the private key is encrypted and on disk uses another JSON encoding.
|
the private key is encrypted and on disk uses another JSON encoding.
|
||||||
|
|
||||||
The crypto is documented at https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
|
The crypto is documented at https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,21 +34,13 @@ func TestBlobs(t *testing.T) {
|
||||||
header := types.Header{}
|
header := types.Header{}
|
||||||
block := types.NewBlock(&header, &types.Body{}, nil, nil)
|
block := types.NewBlock(&header, &types.Body{}, nil, nil)
|
||||||
|
|
||||||
sidecarWithoutCellProofs := &types.BlobTxSidecar{
|
sidecarWithoutCellProofs := types.NewBlobTxSidecar(types.BlobSidecarVersion0, []kzg4844.Blob{*emptyBlob}, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof})
|
||||||
Blobs: []kzg4844.Blob{*emptyBlob},
|
|
||||||
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
|
||||||
Proofs: []kzg4844.Proof{emptyBlobProof},
|
|
||||||
}
|
|
||||||
env := BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithoutCellProofs}, nil)
|
env := BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithoutCellProofs}, nil)
|
||||||
if len(env.BlobsBundle.Proofs) != 1 {
|
if len(env.BlobsBundle.Proofs) != 1 {
|
||||||
t.Fatalf("Expect 1 proof in blobs bundle, got %v", len(env.BlobsBundle.Proofs))
|
t.Fatalf("Expect 1 proof in blobs bundle, got %v", len(env.BlobsBundle.Proofs))
|
||||||
}
|
}
|
||||||
|
|
||||||
sidecarWithCellProofs := &types.BlobTxSidecar{
|
sidecarWithCellProofs := types.NewBlobTxSidecar(types.BlobSidecarVersion0, []kzg4844.Blob{*emptyBlob}, []kzg4844.Commitment{emptyBlobCommit}, emptyCellProof)
|
||||||
Blobs: []kzg4844.Blob{*emptyBlob},
|
|
||||||
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
|
||||||
Proofs: emptyCellProof,
|
|
||||||
}
|
|
||||||
env = BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithCellProofs}, nil)
|
env = BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithCellProofs}, nil)
|
||||||
if len(env.BlobsBundle.Proofs) != 128 {
|
if len(env.BlobsBundle.Proofs) != 128 {
|
||||||
t.Fatalf("Expect 128 proofs in blobs bundle, got %v", len(env.BlobsBundle.Proofs))
|
t.Fatalf("Expect 128 proofs in blobs bundle, got %v", len(env.BlobsBundle.Proofs))
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
0xd60e5310c5d52ced44cfb13be4e9f22a1e6a6dc56964c3cccd429182d26d72d0
|
0x4bae4b97deda095724560012cab1f80a5221ce0a37a4b5236d8ab63f595f29d9
|
||||||
1
beacon/params/checkpoint_hoodi.hex
Normal file
1
beacon/params/checkpoint_hoodi.hex
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0x1bbf958008172591b6cbdb3d8d52e26998258e83d4bdb9eec10969d84519a6bd
|
||||||
|
|
@ -1 +1 @@
|
||||||
0x02f0bb348b0d45f95a9b7e2bb5705768ad06548876cee03d880a2c9dabb1ff88
|
0x2fe39a39b6f7cbd549e0f74d259de6db486005a65bd3bd92840dd6ce21d6f4c8
|
||||||
|
|
@ -1 +1 @@
|
||||||
0xa0dad451a230c01be6f2492980ec5bb412d8cf33351a75e8b172b5b84a5fd03a
|
0x86686b2b366e24134e0e3969a9c5f3759f92e5d2b04785b42e22cc7d468c2107
|
||||||
|
|
@ -31,6 +31,9 @@ var checkpointSepolia string
|
||||||
//go:embed checkpoint_holesky.hex
|
//go:embed checkpoint_holesky.hex
|
||||||
var checkpointHolesky string
|
var checkpointHolesky string
|
||||||
|
|
||||||
|
//go:embed checkpoint_hoodi.hex
|
||||||
|
var checkpointHoodi string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MainnetLightConfig = (&ChainConfig{
|
MainnetLightConfig = (&ChainConfig{
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
||||||
|
|
@ -71,7 +74,7 @@ var (
|
||||||
HoodiLightConfig = (&ChainConfig{
|
HoodiLightConfig = (&ChainConfig{
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x212f13fc4df078b6cb7db228f1c8307566dcecf900867401a92023d7ba99cb5f"),
|
GenesisValidatorsRoot: common.HexToHash("0x212f13fc4df078b6cb7db228f1c8307566dcecf900867401a92023d7ba99cb5f"),
|
||||||
GenesisTime: 1742212800,
|
GenesisTime: 1742212800,
|
||||||
Checkpoint: common.HexToHash(""),
|
Checkpoint: common.HexToHash(checkpointHoodi),
|
||||||
}).
|
}).
|
||||||
AddFork("GENESIS", 0, common.FromHex("0x10000910")).
|
AddFork("GENESIS", 0, common.FromHex("0x10000910")).
|
||||||
AddFork("ALTAIR", 0, common.FromHex("0x20000910")).
|
AddFork("ALTAIR", 0, common.FromHex("0x20000910")).
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# This file contains sha256 checksums of optional build dependencies.
|
# This file contains sha256 checksums of optional build dependencies.
|
||||||
|
|
||||||
# version:spec-tests v4.5.0
|
# version:spec-tests fusaka-devnet-3%40v1.0.0
|
||||||
# https://github.com/ethereum/execution-spec-tests/releases
|
# https://github.com/ethereum/execution-spec-tests/releases
|
||||||
# https://github.com/ethereum/execution-spec-tests/releases/download/v4.5.0/
|
# https://github.com/ethereum/execution-spec-tests/releases/download/fusaka-devnet-3%40v1.0.0
|
||||||
58afb92a0075a2cb7c4dec1281f7cb88b21b02afbedad096b580f3f8cc14c54c fixtures_develop.tar.gz
|
576261e1280e5300c458aa9b05eccb2fec5ff80a0005940dc52fa03fdd907249 fixtures_fusaka-devnet-3.tar.gz
|
||||||
|
|
||||||
# version:golang 1.24.4
|
# version:golang 1.24.4
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ func doTest(cmdline []string) {
|
||||||
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
|
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
|
||||||
func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
|
func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
|
||||||
ext := ".tar.gz"
|
ext := ".tar.gz"
|
||||||
base := "fixtures_develop"
|
base := "fixtures_fusaka-devnet-3"
|
||||||
archivePath := filepath.Join(cachedir, base+ext)
|
archivePath := filepath.Join(cachedir, base+ext)
|
||||||
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
|
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ func (c *Conn) Write(proto Proto, code uint64, msg any) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var errDisc error = fmt.Errorf("disconnect")
|
var errDisc error = errors.New("disconnect")
|
||||||
|
|
||||||
// ReadEth reads an Eth sub-protocol wire message.
|
// ReadEth reads an Eth sub-protocol wire message.
|
||||||
func (c *Conn) ReadEth() (any, error) {
|
func (c *Conn) ReadEth() (any, error) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package ethtest
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -879,11 +880,7 @@ func makeSidecar(data ...byte) *types.BlobTxSidecar {
|
||||||
commitments = append(commitments, c)
|
commitments = append(commitments, c)
|
||||||
proofs = append(proofs, p)
|
proofs = append(proofs, p)
|
||||||
}
|
}
|
||||||
return &types.BlobTxSidecar{
|
return types.NewBlobTxSidecar(types.BlobSidecarVersion0, blobs, commitments, proofs)
|
||||||
Blobs: blobs,
|
|
||||||
Commitments: commitments,
|
|
||||||
Proofs: proofs,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
|
func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
|
||||||
|
|
@ -988,14 +985,10 @@ func (s *Suite) TestBlobViolations(t *utesting.T) {
|
||||||
// data has been modified to produce a different commitment hash.
|
// data has been modified to produce a different commitment hash.
|
||||||
func mangleSidecar(tx *types.Transaction) *types.Transaction {
|
func mangleSidecar(tx *types.Transaction) *types.Transaction {
|
||||||
sidecar := tx.BlobTxSidecar()
|
sidecar := tx.BlobTxSidecar()
|
||||||
copy := types.BlobTxSidecar{
|
cpy := sidecar.Copy()
|
||||||
Blobs: append([]kzg4844.Blob{}, sidecar.Blobs...),
|
|
||||||
Commitments: append([]kzg4844.Commitment{}, sidecar.Commitments...),
|
|
||||||
Proofs: append([]kzg4844.Proof{}, sidecar.Proofs...),
|
|
||||||
}
|
|
||||||
// zero the first commitment to alter the sidecar hash
|
// zero the first commitment to alter the sidecar hash
|
||||||
copy.Commitments[0] = kzg4844.Commitment{}
|
cpy.Commitments[0] = kzg4844.Commitment{}
|
||||||
return tx.WithBlobTxSidecar(©)
|
return tx.WithBlobTxSidecar(cpy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestBlobTxWithoutSidecar(t *utesting.T) {
|
func (s *Suite) TestBlobTxWithoutSidecar(t *utesting.T) {
|
||||||
|
|
@ -1100,7 +1093,7 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !readUntilDisconnect(conn) {
|
if !readUntilDisconnect(conn) {
|
||||||
errc <- fmt.Errorf("expected bad peer to be disconnected")
|
errc <- errors.New("expected bad peer to be disconnected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stage3.Done()
|
stage3.Done()
|
||||||
|
|
@ -1147,7 +1140,7 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.GetPooledTransactionsRequest[0] != tx.Hash() {
|
if req.GetPooledTransactionsRequest[0] != tx.Hash() {
|
||||||
errc <- fmt.Errorf("requested unknown tx hash")
|
errc <- errors.New("requested unknown tx hash")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1157,7 +1150,7 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if readUntilDisconnect(conn) {
|
if readUntilDisconnect(conn) {
|
||||||
errc <- fmt.Errorf("unexpected disconnect")
|
errc <- errors.New("unexpected disconnect")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
close(errc)
|
close(errc)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover/v4wire"
|
"github.com/ethereum/go-ethereum/p2p/discover/v4wire"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -501,6 +502,36 @@ func FindnodeAmplificationWrongIP(t *utesting.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ENRRequest(t *utesting.T) {
|
||||||
|
t.Log(`This test sends an ENRRequest packet and expects a response containing a valid ENR.`)
|
||||||
|
|
||||||
|
te := newTestEnv(Remote, Listen1, Listen2)
|
||||||
|
defer te.close()
|
||||||
|
bond(t, te)
|
||||||
|
|
||||||
|
req := &v4wire.ENRRequest{Expiration: futureExpiration()}
|
||||||
|
hash := te.send(te.l1, req)
|
||||||
|
|
||||||
|
response, _, err := te.read(te.l1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("read error:", err)
|
||||||
|
}
|
||||||
|
enrResp, ok := response.(*v4wire.ENRResponse)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("expected ENRResponse packet, got %T", response)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(enrResp.ReplyTok, hash) {
|
||||||
|
t.Errorf("wrong hash in response packet: got %x, want %x", enrResp.ReplyTok, hash)
|
||||||
|
}
|
||||||
|
node, err := enode.New(enode.ValidSchemes, &enrResp.Record)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("invalid record in response: %v", err)
|
||||||
|
}
|
||||||
|
if node.ID() != te.remote.ID() {
|
||||||
|
t.Errorf("wrong node ID in response: got %v, want %v", node.ID(), te.remote.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var AllTests = []utesting.Test{
|
var AllTests = []utesting.Test{
|
||||||
{Name: "Ping/Basic", Fn: BasicPing},
|
{Name: "Ping/Basic", Fn: BasicPing},
|
||||||
{Name: "Ping/WrongTo", Fn: PingWrongTo},
|
{Name: "Ping/WrongTo", Fn: PingWrongTo},
|
||||||
|
|
@ -510,6 +541,7 @@ var AllTests = []utesting.Test{
|
||||||
{Name: "Ping/PastExpiration", Fn: PingPastExpiration},
|
{Name: "Ping/PastExpiration", Fn: PingPastExpiration},
|
||||||
{Name: "Ping/WrongPacketType", Fn: WrongPacketType},
|
{Name: "Ping/WrongPacketType", Fn: WrongPacketType},
|
||||||
{Name: "Ping/BondThenPingWithWrongFrom", Fn: BondThenPingWithWrongFrom},
|
{Name: "Ping/BondThenPingWithWrongFrom", Fn: BondThenPingWithWrongFrom},
|
||||||
|
{Name: "ENRRequest", Fn: ENRRequest},
|
||||||
{Name: "Findnode/WithoutEndpointProof", Fn: FindnodeWithoutEndpointProof},
|
{Name: "Findnode/WithoutEndpointProof", Fn: FindnodeWithoutEndpointProof},
|
||||||
{Name: "Findnode/BasicFindnode", Fn: BasicFindnode},
|
{Name: "Findnode/BasicFindnode", Fn: BasicFindnode},
|
||||||
{Name: "Findnode/UnsolicitedNeighbors", Fn: UnsolicitedNeighbors},
|
{Name: "Findnode/UnsolicitedNeighbors", Fn: UnsolicitedNeighbors},
|
||||||
|
|
|
||||||
|
|
@ -576,8 +576,8 @@ func parseDumpConfig(ctx *cli.Context, db ethdb.Database) (*state.DumpConfig, co
|
||||||
arg := ctx.Args().First()
|
arg := ctx.Args().First()
|
||||||
if hashish(arg) {
|
if hashish(arg) {
|
||||||
hash := common.HexToHash(arg)
|
hash := common.HexToHash(arg)
|
||||||
if number := rawdb.ReadHeaderNumber(db, hash); number != nil {
|
if number, ok := rawdb.ReadHeaderNumber(db, hash); ok {
|
||||||
header = rawdb.ReadHeader(db, hash, *number)
|
header = rawdb.ReadHeader(db, hash, number)
|
||||||
} else {
|
} else {
|
||||||
return nil, common.Hash{}, fmt.Errorf("block %x not found", hash)
|
return nil, common.Hash{}, fmt.Errorf("block %x not found", hash)
|
||||||
}
|
}
|
||||||
|
|
@ -716,7 +716,7 @@ func downloadEra(ctx *cli.Context) error {
|
||||||
case ctx.IsSet(utils.SepoliaFlag.Name):
|
case ctx.IsSet(utils.SepoliaFlag.Name):
|
||||||
network = "sepolia"
|
network = "sepolia"
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported network, no known era1 checksums")
|
return errors.New("unsupported network, no known era1 checksums")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,14 +262,16 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
||||||
if cfg.Ethstats.URL != "" {
|
if cfg.Ethstats.URL != "" {
|
||||||
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
|
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
|
||||||
}
|
}
|
||||||
// Configure full-sync tester service if requested
|
// Configure synchronization override service
|
||||||
|
var synctarget common.Hash
|
||||||
if ctx.IsSet(utils.SyncTargetFlag.Name) {
|
if ctx.IsSet(utils.SyncTargetFlag.Name) {
|
||||||
hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name))
|
hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name))
|
||||||
if len(hex) != common.HashLength {
|
if len(hex) != common.HashLength {
|
||||||
utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength)
|
utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength)
|
||||||
}
|
}
|
||||||
utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex), ctx.Bool(utils.ExitWhenSyncedFlag.Name))
|
synctarget = common.BytesToHash(hex)
|
||||||
}
|
}
|
||||||
|
utils.RegisterSyncOverrideService(stack, eth, synctarget, ctx.Bool(utils.ExitWhenSyncedFlag.Name))
|
||||||
|
|
||||||
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Start dev mode.
|
// Start dev mode.
|
||||||
|
|
|
||||||
161
cmd/geth/testdata/vcheck/data.json
vendored
161
cmd/geth/testdata/vcheck/data.json
vendored
|
|
@ -6,28 +6,33 @@
|
||||||
"description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.",
|
"description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://github.com/ethereum/go-ethereum/pull/21793",
|
"https://github.com/ethereum/go-ethereum/pull/21793",
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49"
|
"https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49",
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-v592-xf75-856p"
|
||||||
],
|
],
|
||||||
"introduced": "v1.6.0",
|
"introduced": "v1.6.0",
|
||||||
"fixed": "v1.9.24",
|
"fixed": "v1.9.24",
|
||||||
"published": "2020-11-12",
|
"published": "2020-11-12",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.2(1|2|3)-.*"
|
"CVE": "CVE-2020-26240",
|
||||||
|
"check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.\\d-.*|Geth\\/v1\\.9\\.1.*|Geth\\/v1\\.9\\.2(0|1|2|3)-.*"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GoCrash",
|
"name": "Denial of service due to Go CVE-2020-28362",
|
||||||
"uid": "GETH-2020-02",
|
"uid": "GETH-2020-02",
|
||||||
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`",
|
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`",
|
||||||
"description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.",
|
"description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM",
|
"https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM",
|
||||||
"https://github.com/golang/go/issues/42552"
|
"https://github.com/golang/go/issues/42552",
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-m6gx-rhvj-fh52"
|
||||||
],
|
],
|
||||||
|
"introduced": "v0.0.0",
|
||||||
"fixed": "v1.9.24",
|
"fixed": "v1.9.24",
|
||||||
"published": "2020-11-12",
|
"published": "2020-11-12",
|
||||||
"severity": "Critical",
|
"severity": "Critical",
|
||||||
|
"CVE": "CVE-2020-28362",
|
||||||
"check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$"
|
"check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -36,26 +41,162 @@
|
||||||
"summary": "A consensus flaw in Geth, related to `datacopy` precompile",
|
"summary": "A consensus flaw in Geth, related to `datacopy` precompile",
|
||||||
"description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.",
|
"description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/"
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-69v6-xc2j-r2jf"
|
||||||
],
|
],
|
||||||
"introduced": "v1.9.7",
|
"introduced": "v1.9.7",
|
||||||
"fixed": "v1.9.17",
|
"fixed": "v1.9.17",
|
||||||
"published": "2020-11-12",
|
"published": "2020-11-12",
|
||||||
"severity": "Critical",
|
"severity": "Critical",
|
||||||
|
"CVE": "CVE-2020-26241",
|
||||||
"check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$"
|
"check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GethCrash",
|
"name": "Geth DoS via MULMOD",
|
||||||
"uid": "GETH-2020-04",
|
"uid": "GETH-2020-04",
|
||||||
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
||||||
"description": "Full details to be disclosed at a later date",
|
"description": "Affected versions suffer from a vulnerability which can be exploited through the `MULMOD` operation, by specifying a modulo of `0`: `mulmod(a,b,0)`, causing a `panic` in the underlying library. \nThe crash was in the `uint256` library, where a buffer [underflowed](https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L442).\n\n\tif `d == 0`, `dLen` remains `0`\n\nand https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L451 will try to access index `[-1]`.\n\nThe `uint256` library was first merged in this [commit](https://github.com/ethereum/go-ethereum/commit/cf6674539c589f80031f3371a71c6a80addbe454), on 2020-06-08. \nExploiting this vulnerabilty would cause all vulnerable nodes to drop off the network. \n\nThe issue was brought to our attention through a [bug report](https://github.com/ethereum/go-ethereum/issues/21367), showing a `panic` occurring on sync from genesis on the Ropsten network.\n \nIt was estimated that the least obvious way to fix this would be to merge the fix into `uint256`, make a new release of that library and then update the geth-dependency.\n",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/"
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m",
|
||||||
|
"https://github.com/holiman/uint256/releases/tag/v1.1.1",
|
||||||
|
"https://github.com/holiman/uint256/pull/80",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/21368"
|
||||||
],
|
],
|
||||||
"introduced": "v1.9.16",
|
"introduced": "v1.9.16",
|
||||||
"fixed": "v1.9.18",
|
"fixed": "v1.9.18",
|
||||||
"published": "2020-11-12",
|
"published": "2020-11-12",
|
||||||
"severity": "Critical",
|
"severity": "Critical",
|
||||||
|
"CVE": "CVE-2020-26242",
|
||||||
"check": "Geth\\/v1\\.9.(16|17).*$"
|
"check": "Geth\\/v1\\.9.(16|17).*$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LES Server DoS via GetProofsV2",
|
||||||
|
"uid": "GETH-2020-05",
|
||||||
|
"summary": "A DoS vulnerability can make a LES server crash.",
|
||||||
|
"description": "A DoS vulnerability can make a LES server crash via malicious GetProofsV2 request from a connected LES client.\n\nThe vulnerability was patched in #21896.\n\nThis vulnerability only concern users explicitly running geth as a light server",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-r33q-22hv-j29q",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/21896"
|
||||||
|
],
|
||||||
|
"introduced": "v1.8.0",
|
||||||
|
"fixed": "v1.9.25",
|
||||||
|
"published": "2020-12-10",
|
||||||
|
"severity": "Medium",
|
||||||
|
"CVE": "CVE-2020-26264",
|
||||||
|
"check": "(Geth\\/v1\\.8\\.*)|(Geth\\/v1\\.9\\.\\d-.*)|(Geth\\/v1\\.9\\.1\\d-.*)|(Geth\\/v1\\.9\\.(20|21|22|23|24)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SELFDESTRUCT-recreate consensus flaw",
|
||||||
|
"uid": "GETH-2020-06",
|
||||||
|
"introduced": "v1.9.4",
|
||||||
|
"fixed": "v1.9.20",
|
||||||
|
"summary": "A consensus-vulnerability in Geth could cause a chain split, where vulnerable versions refuse to accept the canonical chain.",
|
||||||
|
"description": "A flaw was repoted at 2020-08-11 by John Youngseok Yang (Software Platform Lab), where a particular sequence of transactions could cause a consensus failure.\n\n- Tx 1:\n - `sender` invokes `caller`.\n - `caller` invokes `0xaa`. `0xaa` has 3 wei, does a self-destruct-to-self\n - `caller` does a `1 wei` -call to `0xaa`, who thereby has 1 wei (the code in `0xaa` still executed, since the tx is still ongoing, but doesn't redo the selfdestruct, it takes a different path if callvalue is non-zero)\n\n-Tx 2:\n - `sender` does a 5-wei call to 0xaa. No exec (since no code). \n\nIn geth, the result would be that `0xaa` had `6 wei`, whereas OE reported (correctly) `5` wei. Furthermore, in geth, if the second tx was not executed, the `0xaa` would be destructed, resulting in `0 wei`. Thus obviously wrong. \n\nIt was determined that the root cause was this [commit](https://github.com/ethereum/go-ethereum/commit/223b950944f494a5b4e0957fd9f92c48b09037ad) from [this PR](https://github.com/ethereum/go-ethereum/pull/19953). The semantics of `createObject` was subtly changd, into returning a non-nil object (with `deleted=true`) where it previously did not if the account had been destructed. This return value caused the new object to inherit the old `balance`.\n",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4"
|
||||||
|
],
|
||||||
|
"published": "2020-12-10",
|
||||||
|
"severity": "High",
|
||||||
|
"CVE": "CVE-2020-26265",
|
||||||
|
"check": "(Geth\\/v1\\.9\\.(4|5|6|7|8|9)-.*)|(Geth\\/v1\\.9\\.1\\d-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Not ready for London upgrade",
|
||||||
|
"uid": "GETH-2021-01",
|
||||||
|
"summary": "The client is not ready for the 'London' technical upgrade, and will deviate from the canonical chain when the London upgrade occurs (at block '12965000' around August 4, 2021.",
|
||||||
|
"description": "At (or around) August 4, Ethereum will undergo a technical upgrade called 'London'. Clients not upgraded will fail to progress on the canonical chain.",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md",
|
||||||
|
"https://notes.ethereum.org/@timbeiko/ropsten-postmortem"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.1",
|
||||||
|
"fixed": "v1.10.6",
|
||||||
|
"published": "2021-07-22",
|
||||||
|
"severity": "High",
|
||||||
|
"check": "(Geth\\/v1\\.10\\.(1|2|3|4|5)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "RETURNDATA corruption via datacopy",
|
||||||
|
"uid": "GETH-2021-02",
|
||||||
|
"summary": "A consensus-flaw in the Geth EVM could cause a node to deviate from the canonical chain.",
|
||||||
|
"description": "A memory-corruption bug within the EVM can cause a consensus error, where vulnerable nodes obtain a different `stateRoot` when processing a maliciously crafted transaction. This, in turn, would lead to the chain being split: mainnet splitting in two forks.\n\nAll Geth versions supporting the London hard fork are vulnerable (the bug is older than London), so all users should update.\n\nThis bug was exploited on Mainnet at block 13107518.\n\nCredits for the discovery go to @guidovranken (working for Sentnl during an audit of the Telos EVM) and reported via bounty@ethereum.org.",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/blob/master/docs/postmortems/2021-08-22-split-postmortem.md",
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-9856-9gg9-qcmq",
|
||||||
|
"https://github.com/ethereum/go-ethereum/releases/tag/v1.10.8"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.0",
|
||||||
|
"fixed": "v1.10.8",
|
||||||
|
"published": "2021-08-24",
|
||||||
|
"severity": "High",
|
||||||
|
"CVE": "CVE-2021-39137",
|
||||||
|
"check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DoS via malicious `snap/1` request",
|
||||||
|
"uid": "GETH-2021-03",
|
||||||
|
"summary": "A vulnerable node is susceptible to crash when processing a maliciously crafted message from a peer, via the snap/1 protocol. The crash can be triggered by sending a malicious snap/1 GetTrieNodes package.",
|
||||||
|
"description": "The `snap/1` protocol handler contains two vulnerabilities related to the `GetTrieNodes` packet, which can be exploited to crash the node. Full details are available at the Github security [advisory](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-59hh-656j-3p7v)",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-59hh-656j-3p7v",
|
||||||
|
"https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/23657"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.0",
|
||||||
|
"fixed": "v1.10.9",
|
||||||
|
"published": "2021-10-24",
|
||||||
|
"severity": "Medium",
|
||||||
|
"CVE": "CVE-2021-41173",
|
||||||
|
"check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7|8)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DoS via malicious p2p message",
|
||||||
|
"uid": "GETH-2022-01",
|
||||||
|
"summary": "A vulnerable node can crash via p2p messages sent from an attacker node, if running with non-default log options.",
|
||||||
|
"description": "A vulnerable node, if configured to use high verbosity logging, can be made to crash when handling specially crafted p2p messages sent from an attacker node. Full details are available at the Github security [advisory](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-wjxw-gh3m-7pm5)",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-wjxw-gh3m-7pm5",
|
||||||
|
"https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/24507"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.0",
|
||||||
|
"fixed": "v1.10.17",
|
||||||
|
"published": "2022-05-11",
|
||||||
|
"severity": "Low",
|
||||||
|
"CVE": "CVE-2022-29177",
|
||||||
|
"check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DoS via malicious p2p message",
|
||||||
|
"uid": "GETH-2023-01",
|
||||||
|
"summary": "A vulnerable node can be made to consume unbounded amounts of memory when handling specially crafted p2p messages sent from an attacker node.",
|
||||||
|
"description": "The p2p handler spawned a new goroutine to respond to ping requests. By flooding a node with ping requests, an unbounded number of goroutines can be created, leading to resource exhaustion and potentially crash due to OOM.",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-ppjg-v974-84cm",
|
||||||
|
"https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.0",
|
||||||
|
"fixed": "v1.12.1",
|
||||||
|
"published": "2023-09-06",
|
||||||
|
"severity": "High",
|
||||||
|
"CVE": "CVE-2023-40591",
|
||||||
|
"check": "(Geth\\/v1\\.(10|11)\\..*)|(Geth\\/v1\\.12\\.0-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DoS via malicious p2p message",
|
||||||
|
"uid": "GETH-2024-01",
|
||||||
|
"summary": "A vulnerable node can be made to consume very large amounts of memory when handling specially crafted p2p messages sent from an attacker node.",
|
||||||
|
"description": "A vulnerable node can be made to consume very large amounts of memory when handling specially crafted p2p messages sent from an attacker node. Full details will be available at the Github security [advisory](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-4xc9-8hmq-j652)",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-4xc9-8hmq-j652",
|
||||||
|
"https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.0",
|
||||||
|
"fixed": "v1.13.15",
|
||||||
|
"published": "2024-05-06",
|
||||||
|
"severity": "High",
|
||||||
|
"CVE": "CVE-2024-32972",
|
||||||
|
"check": "(Geth\\/v1\\.(10|11|12)\\..*)|(Geth\\/v1\\.13\\.\\d-.*)|(Geth\\/v1\\.13\\.1(0|1|2|3|4)-.*)$"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
untrusted comment: signature from minisign secret key
|
untrusted comment: signature from minisign secret key
|
||||||
RUQkliYstQBOKLK05Sy5f3bVRMBqJT26ABo6Vbp3BNJAVjejoqYCu4GWE/+7qcDfHBqYIniDCbFIUvYEnOHxV6vZ93wO1xJWDQw=
|
RUQkliYstQBOKHklFEYCUjepz81dyUuDmIAxjAvXa+icjGuKcjtVfV06G7qfOMSpplS5EcntU12n+AnGNyuOM8zIctaIWcfG2w0=
|
||||||
trusted comment: timestamp:1693986492 file:data.json hashed
|
trusted comment: timestamp:1752094689 file:data.json hashed
|
||||||
6Fdw2H+W1ZXK7QXSF77Z5AWC7+AEFAfDmTSxNGylU5HLT1AuSJQmxslj+VjtUBamYCvOuET7plbXza942AlWDw==
|
u2e4wo4HBTU6viQTSY/NVBHoWoPFJnnTvLZS0FYl3JdvSOYi6+qpbEsDhAIFqq/n8VmlS/fPqqf7vKCNiAgjAA==
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
untrusted comment: signature from minisign secret key
|
untrusted comment: signature from minisign secret key
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
RWQkliYstQBOKNoyq2O98hPmeVJQ6ShQLM58+4n0gkY0y0trFMDAsHuN/l4IyHfh8dDQ1ry0+IuZVrf/i8M/P3YFzFfAymDYCQ0=
|
||||||
trusted comment: timestamp:1605618622 file:vulnerabilities.json
|
trusted comment: timestamp:1752094703 file:data.json
|
||||||
osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ==
|
cNyq3ZGlqo785HtWODb9ejWqF0HhSeXuLGXzC7z1IhnDrBObWBJngYd3qBG1dQcYlHQ+bgB/On5mSyMFn4UoCQ==
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
untrusted comment: Here's a comment
|
untrusted comment: Here's a comment
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
RWQkliYstQBOKNoyq2O98hPmeVJQ6ShQLM58+4n0gkY0y0trFMDAsHuN/l4IyHfh8dDQ1ry0+IuZVrf/i8M/P3YFzFfAymDYCQ0=
|
||||||
trusted comment: Here's a trusted comment
|
trusted comment: Here's a trusted comment
|
||||||
3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ==
|
dL7lO8sqFFCOXJO/u8SgoDk2nlXGWPRDbOTJkChMbmtUp9PB7sG831basXkZ/0CQ/l/vG7AbPyMNEVZyJn5NCg==
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
untrusted comment: One more (untrusted) comment
|
untrusted comment: One more (untrusted™) comment
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
RWQkliYstQBOKNoyq2O98hPmeVJQ6ShQLM58+4n0gkY0y0trFMDAsHuN/l4IyHfh8dDQ1ry0+IuZVrf/i8M/P3YFzFfAymDYCQ0=
|
||||||
trusted comment: Here's a trusted comment
|
trusted comment: Here's a trusted comment
|
||||||
3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ==
|
dL7lO8sqFFCOXJO/u8SgoDk2nlXGWPRDbOTJkChMbmtUp9PB7sG831basXkZ/0CQ/l/vG7AbPyMNEVZyJn5NCg==
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
untrusted comment: verify with ./signifykey.pub
|
untrusted comment: verify with signifykey.pub
|
||||||
RWSKLNhZb0KdAbhRUhW2LQZXdnwttu2SYhM9EuC4mMgOJB85h7/YIPupf8/ldTs4N8e9Y/fhgdY40q5LQpt5IFC62fq0v8U1/w8=
|
RWSKLNhZb0KdARbMcGN40hbHzKQYZDgDOFhEUT1YpzMnqre/mbKJ8td/HVlG03Am1YCszATiI0DbnljjTy4iNHYwqBfzrFUqUg0=
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
untrusted comment: signature from minisign secret key
|
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
|
||||||
trusted comment: timestamp:1605618622 file:vulnerabilities.json
|
|
||||||
osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ==
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
untrusted comment: Here's a comment
|
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
|
||||||
trusted comment: Here's a trusted comment
|
|
||||||
3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ==
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
untrusted comment: One more (untrusted) comment
|
|
||||||
RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0=
|
|
||||||
trusted comment: Here's a trusted comment
|
|
||||||
3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ==
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
"description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.",
|
"description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://github.com/ethereum/go-ethereum/pull/21793",
|
"https://github.com/ethereum/go-ethereum/pull/21793",
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49",
|
"https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49",
|
||||||
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-v592-xf75-856p"
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-v592-xf75-856p"
|
||||||
],
|
],
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`",
|
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`",
|
||||||
"description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.",
|
"description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM",
|
"https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM",
|
||||||
"https://github.com/golang/go/issues/42552",
|
"https://github.com/golang/go/issues/42552",
|
||||||
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-m6gx-rhvj-fh52"
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-m6gx-rhvj-fh52"
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
"summary": "A consensus flaw in Geth, related to `datacopy` precompile",
|
"summary": "A consensus flaw in Geth, related to `datacopy` precompile",
|
||||||
"description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.",
|
"description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-69v6-xc2j-r2jf"
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-69v6-xc2j-r2jf"
|
||||||
],
|
],
|
||||||
"introduced": "v1.9.7",
|
"introduced": "v1.9.7",
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
||||||
"description": "Affected versions suffer from a vulnerability which can be exploited through the `MULMOD` operation, by specifying a modulo of `0`: `mulmod(a,b,0)`, causing a `panic` in the underlying library. \nThe crash was in the `uint256` library, where a buffer [underflowed](https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L442).\n\n\tif `d == 0`, `dLen` remains `0`\n\nand https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L451 will try to access index `[-1]`.\n\nThe `uint256` library was first merged in this [commit](https://github.com/ethereum/go-ethereum/commit/cf6674539c589f80031f3371a71c6a80addbe454), on 2020-06-08. \nExploiting this vulnerabilty would cause all vulnerable nodes to drop off the network. \n\nThe issue was brought to our attention through a [bug report](https://github.com/ethereum/go-ethereum/issues/21367), showing a `panic` occurring on sync from genesis on the Ropsten network.\n \nIt was estimated that the least obvious way to fix this would be to merge the fix into `uint256`, make a new release of that library and then update the geth-dependency.\n",
|
"description": "Affected versions suffer from a vulnerability which can be exploited through the `MULMOD` operation, by specifying a modulo of `0`: `mulmod(a,b,0)`, causing a `panic` in the underlying library. \nThe crash was in the `uint256` library, where a buffer [underflowed](https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L442).\n\n\tif `d == 0`, `dLen` remains `0`\n\nand https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L451 will try to access index `[-1]`.\n\nThe `uint256` library was first merged in this [commit](https://github.com/ethereum/go-ethereum/commit/cf6674539c589f80031f3371a71c6a80addbe454), on 2020-06-08. \nExploiting this vulnerabilty would cause all vulnerable nodes to drop off the network. \n\nThe issue was brought to our attention through a [bug report](https://github.com/ethereum/go-ethereum/issues/21367), showing a `panic` occurring on sync from genesis on the Ropsten network.\n \nIt was estimated that the least obvious way to fix this would be to merge the fix into `uint256`, make a new release of that library and then update the geth-dependency.\n",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth-security-release",
|
||||||
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m",
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m",
|
||||||
"https://github.com/holiman/uint256/releases/tag/v1.1.1",
|
"https://github.com/holiman/uint256/releases/tag/v1.1.1",
|
||||||
"https://github.com/holiman/uint256/pull/80",
|
"https://github.com/holiman/uint256/pull/80",
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ func TestVerification(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
||||||
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
||||||
|
// 1. `minisign -S -l -s ./minisign.sec -m data.json -x ./minisig-sigs/vulnerabilities.json.minisig.1 -c "signature from minisign secret key"`
|
||||||
|
// 2. `minisign -S -l -s ./minisign.sec -m vulnerabilities.json -x ./minisig-sigs/vulnerabilities.json.minisig.2 -c "Here's a comment" -t "Here's a trusted comment"`
|
||||||
|
// 3. minisign -S -l -s ./minisign.sec -m vulnerabilities.json -x ./minisig-sigs/vulnerabilities.json.minisig.3 -c "One more (untrusted™) comment" -t "Here's a trusted comment"
|
||||||
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
||||||
testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
|
testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
|
||||||
})
|
})
|
||||||
|
|
@ -43,7 +46,7 @@ func TestVerification(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
// For this test, the pubkey is in testdata/vcheck/minisign.pub
|
||||||
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
|
||||||
// `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig`
|
// `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig`
|
||||||
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
|
||||||
testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/")
|
testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/")
|
||||||
})
|
})
|
||||||
|
|
@ -53,6 +56,7 @@ func TestVerification(t *testing.T) {
|
||||||
t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
|
t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
|
||||||
// For this test, the pubkey is in testdata/vcheck/signifykey.pub
|
// For this test, the pubkey is in testdata/vcheck/signifykey.pub
|
||||||
// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
|
// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
|
||||||
|
// `signify -S -s signifykey.sec -m data.json -x ./signify-sigs/data.json.sig`
|
||||||
pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
|
pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
|
||||||
testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
|
testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/catalyst"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/syncer"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/remotedb"
|
"github.com/ethereum/go-ethereum/ethdb/remotedb"
|
||||||
|
|
@ -1997,10 +1997,14 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
|
||||||
return filterSystem
|
return filterSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterFullSyncTester adds the full-sync tester service into node.
|
// RegisterSyncOverrideService adds the synchronization override service into node.
|
||||||
func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash, exitWhenSynced bool) {
|
func RegisterSyncOverrideService(stack *node.Node, eth *eth.Ethereum, target common.Hash, exitWhenSynced bool) {
|
||||||
catalyst.RegisterFullSyncTester(stack, eth, target, exitWhenSynced)
|
if target != (common.Hash{}) {
|
||||||
log.Info("Registered full-sync tester", "hash", target, "exitWhenSynced", exitWhenSynced)
|
log.Info("Registered sync override service", "hash", target, "exitWhenSynced", exitWhenSynced)
|
||||||
|
} else {
|
||||||
|
log.Info("Registered sync override service")
|
||||||
|
}
|
||||||
|
syncer.Register(stack, eth, target, exitWhenSynced)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupMetrics configures the metrics system.
|
// SetupMetrics configures the metrics system.
|
||||||
|
|
@ -2198,6 +2202,12 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
||||||
// Disable transaction indexing/unindexing.
|
// Disable transaction indexing/unindexing.
|
||||||
TxLookupLimit: -1,
|
TxLookupLimit: -1,
|
||||||
|
|
||||||
|
// Enables file journaling for the trie database. The journal files will be stored
|
||||||
|
// within the data directory. The corresponding paths will be either:
|
||||||
|
// - DATADIR/triedb/merkle.journal
|
||||||
|
// - DATADIR/triedb/verkle.journal
|
||||||
|
TrieJournalDirectory: stack.ResolvePath("triedb"),
|
||||||
}
|
}
|
||||||
if options.ArchiveMode && !options.Preimages {
|
if options.ArchiveMode && !options.Preimages {
|
||||||
options.Preimages = true
|
options.Preimages = true
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"errors"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ type testConfig struct {
|
||||||
traceTestFile string
|
traceTestFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
var errPrunedHistory = fmt.Errorf("attempt to access pruned history")
|
var errPrunedHistory = errors.New("attempt to access pruned history")
|
||||||
|
|
||||||
// validateHistoryPruneErr checks whether the given error is caused by access
|
// validateHistoryPruneErr checks whether the given error is caused by access
|
||||||
// to history before the pruning threshold block (it is an rpc.Error with code 4444).
|
// to history before the pruning threshold block (it is an rpc.Error with code 4444).
|
||||||
|
|
@ -109,7 +109,7 @@ func validateHistoryPruneErr(err error, blockNum uint64, historyPruneBlock *uint
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == 4444 {
|
if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == 4444 {
|
||||||
if historyPruneBlock != nil && blockNum > *historyPruneBlock {
|
if historyPruneBlock != nil && blockNum > *historyPruneBlock {
|
||||||
return fmt.Errorf("pruned history error returned after pruning threshold")
|
return errors.New("pruned history error returned after pruning threshold")
|
||||||
}
|
}
|
||||||
return errPrunedHistory
|
return errPrunedHistory
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,10 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/bits"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
const uintBits = 32 << (uint64(^uint(0)) >> 63)
|
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
var (
|
var (
|
||||||
ErrEmptyString = &decError{"empty hex string"}
|
ErrEmptyString = &decError{"empty hex string"}
|
||||||
|
|
@ -48,7 +47,7 @@ var (
|
||||||
ErrEmptyNumber = &decError{"hex string \"0x\""}
|
ErrEmptyNumber = &decError{"hex string \"0x\""}
|
||||||
ErrLeadingZero = &decError{"hex number with leading zero digits"}
|
ErrLeadingZero = &decError{"hex number with leading zero digits"}
|
||||||
ErrUint64Range = &decError{"hex number > 64 bits"}
|
ErrUint64Range = &decError{"hex number > 64 bits"}
|
||||||
ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
|
ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", bits.UintSize)}
|
||||||
ErrBig256Range = &decError{"hex number > 256 bits"}
|
ErrBig256Range = &decError{"hex number > 256 bits"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/bits"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -384,7 +385,7 @@ func TestUnmarshalUint(t *testing.T) {
|
||||||
for _, test := range unmarshalUintTests {
|
for _, test := range unmarshalUintTests {
|
||||||
var v Uint
|
var v Uint
|
||||||
err := json.Unmarshal([]byte(test.input), &v)
|
err := json.Unmarshal([]byte(test.input), &v)
|
||||||
if uintBits == 32 && test.wantErr32bit != nil {
|
if bits.UintSize == 32 && test.wantErr32bit != nil {
|
||||||
checkError(t, test.input, err, test.wantErr32bit)
|
checkError(t, test.input, err, test.wantErr32bit)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
|
|
||||||
"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"
|
||||||
"github.com/ethereum/go-ethereum/params/forks"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -100,42 +99,53 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim
|
||||||
|
|
||||||
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
||||||
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
||||||
var frac uint64
|
blobConfig := latestBlobConfig(config, header.Time)
|
||||||
switch config.LatestFork(header.Time) {
|
if blobConfig == nil {
|
||||||
case forks.Osaka:
|
|
||||||
frac = config.BlobScheduleConfig.Osaka.UpdateFraction
|
|
||||||
case forks.Prague:
|
|
||||||
frac = config.BlobScheduleConfig.Prague.UpdateFraction
|
|
||||||
case forks.Cancun:
|
|
||||||
frac = config.BlobScheduleConfig.Cancun.UpdateFraction
|
|
||||||
default:
|
|
||||||
panic("calculating blob fee on unsupported fork")
|
panic("calculating blob fee on unsupported fork")
|
||||||
}
|
}
|
||||||
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(frac))
|
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(blobConfig.UpdateFraction))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
|
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
|
||||||
func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
||||||
if cfg.BlobScheduleConfig == nil {
|
blobConfig := latestBlobConfig(cfg, time)
|
||||||
|
if blobConfig == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
return blobConfig.Max
|
||||||
|
}
|
||||||
|
|
||||||
|
func latestBlobConfig(cfg *params.ChainConfig, time uint64) *params.BlobConfig {
|
||||||
|
if cfg.BlobScheduleConfig == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
london = cfg.LondonBlock
|
london = cfg.LondonBlock
|
||||||
s = cfg.BlobScheduleConfig
|
s = cfg.BlobScheduleConfig
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
|
case cfg.IsBPO5(london, time) && s.BPO5 != nil:
|
||||||
|
return s.BPO5
|
||||||
|
case cfg.IsBPO4(london, time) && s.BPO4 != nil:
|
||||||
|
return s.BPO4
|
||||||
|
case cfg.IsBPO3(london, time) && s.BPO3 != nil:
|
||||||
|
return s.BPO3
|
||||||
|
case cfg.IsBPO2(london, time) && s.BPO2 != nil:
|
||||||
|
return s.BPO2
|
||||||
|
case cfg.IsBPO1(london, time) && s.BPO1 != nil:
|
||||||
|
return s.BPO1
|
||||||
case cfg.IsOsaka(london, time) && s.Osaka != nil:
|
case cfg.IsOsaka(london, time) && s.Osaka != nil:
|
||||||
return s.Osaka.Max
|
return s.Osaka
|
||||||
case cfg.IsPrague(london, time) && s.Prague != nil:
|
case cfg.IsPrague(london, time) && s.Prague != nil:
|
||||||
return s.Prague.Max
|
return s.Prague
|
||||||
case cfg.IsCancun(london, time) && s.Cancun != nil:
|
case cfg.IsCancun(london, time) && s.Cancun != nil:
|
||||||
return s.Cancun.Max
|
return s.Cancun
|
||||||
default:
|
default:
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxBlobsPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp.
|
// MaxBlobGasPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp.
|
||||||
func MaxBlobGasPerBlock(cfg *params.ChainConfig, time uint64) uint64 {
|
func MaxBlobGasPerBlock(cfg *params.ChainConfig, time uint64) uint64 {
|
||||||
return uint64(MaxBlobsPerBlock(cfg, time)) * params.BlobTxBlobGasPerBlob
|
return uint64(MaxBlobsPerBlock(cfg, time)) * params.BlobTxBlobGasPerBlob
|
||||||
}
|
}
|
||||||
|
|
@ -148,6 +158,16 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
|
case s.BPO5 != nil:
|
||||||
|
return s.BPO5.Max
|
||||||
|
case s.BPO4 != nil:
|
||||||
|
return s.BPO4.Max
|
||||||
|
case s.BPO3 != nil:
|
||||||
|
return s.BPO3.Max
|
||||||
|
case s.BPO2 != nil:
|
||||||
|
return s.BPO2.Max
|
||||||
|
case s.BPO1 != nil:
|
||||||
|
return s.BPO1.Max
|
||||||
case s.Osaka != nil:
|
case s.Osaka != nil:
|
||||||
return s.Osaka.Max
|
return s.Osaka.Max
|
||||||
case s.Prague != nil:
|
case s.Prague != nil:
|
||||||
|
|
@ -161,23 +181,11 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
|
||||||
|
|
||||||
// targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
|
// targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
|
||||||
func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
||||||
if cfg.BlobScheduleConfig == nil {
|
blobConfig := latestBlobConfig(cfg, time)
|
||||||
return 0
|
if blobConfig == nil {
|
||||||
}
|
|
||||||
var (
|
|
||||||
london = cfg.LondonBlock
|
|
||||||
s = cfg.BlobScheduleConfig
|
|
||||||
)
|
|
||||||
switch {
|
|
||||||
case cfg.IsOsaka(london, time) && s.Osaka != nil:
|
|
||||||
return s.Osaka.Target
|
|
||||||
case cfg.IsPrague(london, time) && s.Prague != nil:
|
|
||||||
return s.Prague.Target
|
|
||||||
case cfg.IsCancun(london, time) && s.Cancun != nil:
|
|
||||||
return s.Cancun.Target
|
|
||||||
default:
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
return blobConfig.Target
|
||||||
}
|
}
|
||||||
|
|
||||||
// fakeExponential approximates factor * e ** (numerator / denominator) using
|
// fakeExponential approximates factor * e ** (numerator / denominator) using
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,11 @@ const (
|
||||||
// BlockChainConfig contains the configuration of the BlockChain object.
|
// BlockChainConfig contains the configuration of the BlockChain object.
|
||||||
type BlockChainConfig struct {
|
type BlockChainConfig struct {
|
||||||
// Trie database related options
|
// Trie database related options
|
||||||
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
||||||
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
||||||
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
||||||
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
||||||
|
TrieJournalDirectory string // Directory path to the journal used for persisting trie data across node restarts
|
||||||
|
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
||||||
|
|
@ -246,6 +247,7 @@ func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||||
EnableStateIndexing: cfg.ArchiveMode,
|
EnableStateIndexing: cfg.ArchiveMode,
|
||||||
TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024,
|
TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024,
|
||||||
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
||||||
|
JournalDirectory: cfg.TrieJournalDirectory,
|
||||||
|
|
||||||
// TODO(rjl493456442): The write buffer represents the memory limit used
|
// TODO(rjl493456442): The write buffer represents the memory limit used
|
||||||
// for flushing both trie data and state data to disk. The config name
|
// for flushing both trie data and state data to disk. The config name
|
||||||
|
|
@ -680,7 +682,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
predefinedPoint := history.PrunePoints[bc.genesisBlock.Hash()]
|
predefinedPoint := history.PrunePoints[bc.genesisBlock.Hash()]
|
||||||
if predefinedPoint == nil || freezerTail != predefinedPoint.BlockNumber {
|
if predefinedPoint == nil || freezerTail != predefinedPoint.BlockNumber {
|
||||||
log.Error("Chain history database is pruned with unknown configuration", "tail", freezerTail)
|
log.Error("Chain history database is pruned with unknown configuration", "tail", freezerTail)
|
||||||
return fmt.Errorf("unexpected database tail")
|
return errors.New("unexpected database tail")
|
||||||
}
|
}
|
||||||
bc.historyPrunePoint.Store(predefinedPoint)
|
bc.historyPrunePoint.Store(predefinedPoint)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -693,15 +695,15 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
// action to happen. So just tell them how to do it.
|
// action to happen. So just tell them how to do it.
|
||||||
log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cfg.ChainHistoryMode.String()))
|
log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cfg.ChainHistoryMode.String()))
|
||||||
log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history."))
|
log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history."))
|
||||||
return fmt.Errorf("history pruning requested via configuration")
|
return errors.New("history pruning requested via configuration")
|
||||||
}
|
}
|
||||||
predefinedPoint := history.PrunePoints[bc.genesisBlock.Hash()]
|
predefinedPoint := history.PrunePoints[bc.genesisBlock.Hash()]
|
||||||
if predefinedPoint == nil {
|
if predefinedPoint == nil {
|
||||||
log.Error("Chain history pruning is not supported for this network", "genesis", bc.genesisBlock.Hash())
|
log.Error("Chain history pruning is not supported for this network", "genesis", bc.genesisBlock.Hash())
|
||||||
return fmt.Errorf("history pruning requested for unknown network")
|
return errors.New("history pruning requested for unknown network")
|
||||||
} else if freezerTail > 0 && freezerTail != predefinedPoint.BlockNumber {
|
} else if freezerTail > 0 && freezerTail != predefinedPoint.BlockNumber {
|
||||||
log.Error("Chain history database is pruned to unknown block", "tail", freezerTail)
|
log.Error("Chain history database is pruned to unknown block", "tail", freezerTail)
|
||||||
return fmt.Errorf("unexpected database tail")
|
return errors.New("unexpected database tail")
|
||||||
}
|
}
|
||||||
bc.historyPrunePoint.Store(predefinedPoint)
|
bc.historyPrunePoint.Store(predefinedPoint)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,10 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
|
|
||||||
// GetBlockNumber retrieves the block number associated with a block hash.
|
// GetBlockNumber retrieves the block number associated with a block hash.
|
||||||
func (bc *BlockChain) GetBlockNumber(hash common.Hash) *uint64 {
|
func (bc *BlockChain) GetBlockNumber(hash common.Hash) *uint64 {
|
||||||
return bc.hc.GetBlockNumber(hash)
|
if num, ok := bc.hc.GetBlockNumber(hash); ok {
|
||||||
|
return &num
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going
|
// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going
|
||||||
|
|
@ -107,11 +110,11 @@ func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
|
||||||
if cached, ok := bc.bodyCache.Get(hash); ok {
|
if cached, ok := bc.bodyCache.Get(hash); ok {
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
number := bc.hc.GetBlockNumber(hash)
|
number, ok := bc.hc.GetBlockNumber(hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
body := rawdb.ReadBody(bc.db, hash, *number)
|
body := rawdb.ReadBody(bc.db, hash, number)
|
||||||
if body == nil {
|
if body == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -127,11 +130,11 @@ func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue {
|
||||||
if cached, ok := bc.bodyRLPCache.Get(hash); ok {
|
if cached, ok := bc.bodyRLPCache.Get(hash); ok {
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
number := bc.hc.GetBlockNumber(hash)
|
number, ok := bc.hc.GetBlockNumber(hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
body := rawdb.ReadBodyRLP(bc.db, hash, *number)
|
body := rawdb.ReadBodyRLP(bc.db, hash, number)
|
||||||
if len(body) == 0 {
|
if len(body) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -180,11 +183,11 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||||
|
|
||||||
// GetBlockByHash retrieves a block from the database by hash, caching it if found.
|
// GetBlockByHash retrieves a block from the database by hash, caching it if found.
|
||||||
func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
|
func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
|
||||||
number := bc.hc.GetBlockNumber(hash)
|
number, ok := bc.hc.GetBlockNumber(hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return bc.GetBlock(hash, *number)
|
return bc.GetBlock(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockByNumber retrieves a block from the database by number, caching it
|
// GetBlockByNumber retrieves a block from the database by number, caching it
|
||||||
|
|
@ -200,18 +203,18 @@ func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
|
||||||
// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
|
// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
|
||||||
// [deprecated by eth/62]
|
// [deprecated by eth/62]
|
||||||
func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
|
func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
|
||||||
number := bc.hc.GetBlockNumber(hash)
|
number, ok := bc.hc.GetBlockNumber(hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
block := bc.GetBlock(hash, *number)
|
block := bc.GetBlock(hash, number)
|
||||||
if block == nil {
|
if block == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
blocks = append(blocks, block)
|
blocks = append(blocks, block)
|
||||||
hash = block.ParentHash()
|
hash = block.ParentHash()
|
||||||
*number--
|
number--
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -259,15 +262,15 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
if receipts, ok := bc.receiptsCache.Get(hash); ok {
|
if receipts, ok := bc.receiptsCache.Get(hash); ok {
|
||||||
return receipts
|
return receipts
|
||||||
}
|
}
|
||||||
number := rawdb.ReadHeaderNumber(bc.db, hash)
|
number, ok := rawdb.ReadHeaderNumber(bc.db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
header := bc.GetHeader(hash, *number)
|
header := bc.GetHeader(hash, number)
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
receipts := rawdb.ReadReceipts(bc.db, hash, *number, header.Time, bc.chainConfig)
|
receipts := rawdb.ReadReceipts(bc.db, hash, number, header.Time, bc.chainConfig)
|
||||||
if receipts == nil {
|
if receipts == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -286,11 +289,11 @@ func (bc *BlockChain) GetRawReceipts(hash common.Hash, number uint64) types.Rece
|
||||||
|
|
||||||
// GetReceiptsRLP retrieves the receipts of a block.
|
// GetReceiptsRLP retrieves the receipts of a block.
|
||||||
func (bc *BlockChain) GetReceiptsRLP(hash common.Hash) rlp.RawValue {
|
func (bc *BlockChain) GetReceiptsRLP(hash common.Hash) rlp.RawValue {
|
||||||
number := rawdb.ReadHeaderNumber(bc.db, hash)
|
number, ok := rawdb.ReadHeaderNumber(bc.db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return rawdb.ReadReceiptsRLP(bc.db, hash, *number)
|
return rawdb.ReadReceiptsRLP(bc.db, hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnclesInChain retrieves all the uncles from a given block backwards until
|
// GetUnclesInChain retrieves all the uncles from a given block backwards until
|
||||||
|
|
|
||||||
|
|
@ -782,13 +782,13 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that hash-to-number mappings are present in all databases.
|
// Check that hash-to-number mappings are present in all databases.
|
||||||
if m := rawdb.ReadHeaderNumber(fastDb, hash); m == nil || *m != num {
|
if m, ok := rawdb.ReadHeaderNumber(fastDb, hash); !ok || m != num {
|
||||||
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in fastdb: %v", num, hash, m)
|
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in fastdb: %v", num, hash, m)
|
||||||
}
|
}
|
||||||
if m := rawdb.ReadHeaderNumber(ancientDb, hash); m == nil || *m != num {
|
if m, ok := rawdb.ReadHeaderNumber(ancientDb, hash); !ok || m != num {
|
||||||
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in ancientdb: %v", num, hash, m)
|
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in ancientdb: %v", num, hash, m)
|
||||||
}
|
}
|
||||||
if m := rawdb.ReadHeaderNumber(archiveDb, hash); m == nil || *m != num {
|
if m, ok := rawdb.ReadHeaderNumber(archiveDb, hash); !ok || m != num {
|
||||||
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in archivedb: %v", num, hash, m)
|
t.Errorf("block #%d [%x]: wrong hash-to-number mapping in archivedb: %v", num, hash, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,9 @@ var (
|
||||||
// ErrMissingBlobHashes is returned if a blob transaction has no blob hashes.
|
// ErrMissingBlobHashes is returned if a blob transaction has no blob hashes.
|
||||||
ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes")
|
ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes")
|
||||||
|
|
||||||
|
// ErrTooManyBlobs is returned if a blob transaction exceeds the maximum number of blobs.
|
||||||
|
ErrTooManyBlobs = errors.New("blob transaction has too many blobs")
|
||||||
|
|
||||||
// ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
|
// ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
|
||||||
ErrBlobTxCreate = errors.New("blob transaction of type create")
|
ErrBlobTxCreate = errors.New("blob transaction of type create")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,11 @@
|
||||||
{"blockNumber": 3221725, "blockId": "0xe771f897dece48b1583cc1d1d10de8015da57407eb1fdf239fdbe46eaab85143", "firstIndex": 1140850137},
|
{"blockNumber": 3221725, "blockId": "0xe771f897dece48b1583cc1d1d10de8015da57407eb1fdf239fdbe46eaab85143", "firstIndex": 1140850137},
|
||||||
{"blockNumber": 3357164, "blockId": "0x6252d0aa54c79623b0680069c88d7b5c47983f0d5c4845b6c811b8d9b5e8ff3c", "firstIndex": 1207959453},
|
{"blockNumber": 3357164, "blockId": "0x6252d0aa54c79623b0680069c88d7b5c47983f0d5c4845b6c811b8d9b5e8ff3c", "firstIndex": 1207959453},
|
||||||
{"blockNumber": 3447019, "blockId": "0xeb7d585e1e063f3cc05ed399fbf6c2df63c271f62f030acb804e9fb1e74b6dc1", "firstIndex": 1275067542},
|
{"blockNumber": 3447019, "blockId": "0xeb7d585e1e063f3cc05ed399fbf6c2df63c271f62f030acb804e9fb1e74b6dc1", "firstIndex": 1275067542},
|
||||||
{"blockNumber": 3546397, "blockId": "0xdabdef7defa4281180a57c5af121877b82274f15ccf074ea0096146f4c246df2", "firstIndex": 1342176778}
|
{"blockNumber": 3546397, "blockId": "0xdabdef7defa4281180a57c5af121877b82274f15ccf074ea0096146f4c246df2", "firstIndex": 1342176778},
|
||||||
|
{"blockNumber": 3867885, "blockId": "0x8be069dd7a3e2ffb869ee164d11b28555233d2510b134ab9d5484fdae55d2225", "firstIndex": 1409285539},
|
||||||
|
{"blockNumber": 3935446, "blockId": "0xc91a61bc215bbcccc3020c62e5c8153162df0d8bcc59813d74671b2d24903ed7", "firstIndex": 1476394742},
|
||||||
|
{"blockNumber": 3989508, "blockId": "0xc85dec36a767e44237842ef51915944c2a49780c8c394a3aa6cfb013c99cf58b", "firstIndex": 1543503452},
|
||||||
|
{"blockNumber": 4057078, "blockId": "0xccdb79f6705629cb6ab1667a1244938f60911236549143fcff23a3989213e67e", "firstIndex": 1610612030},
|
||||||
|
{"blockNumber": 4126499, "blockId": "0x92f2ef21fc911e87e81e38373d5f2915587b9648a0ab3cf4fcfe3e5aaffe7b85", "firstIndex": 1677720416},
|
||||||
|
{"blockNumber": 4239335, "blockId": "0x64fbd22965eb583a584552b7edb9b7ce26fb6aad247c1063d0d5a4d11cbcc58c", "firstIndex": 1744830176}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -267,5 +267,26 @@
|
||||||
{"blockNumber": 22168652, "blockId": "0x6ae43618c915e636794e2cc2d75dde9992766881c7405fe6479c045ed4bee57e", "firstIndex": 17850956277},
|
{"blockNumber": 22168652, "blockId": "0x6ae43618c915e636794e2cc2d75dde9992766881c7405fe6479c045ed4bee57e", "firstIndex": 17850956277},
|
||||||
{"blockNumber": 22190975, "blockId": "0x9437121647899a4b7b84d67fbea7cc6ff967481c2eab4328ccd86e2cefe19420", "firstIndex": 17918066140},
|
{"blockNumber": 22190975, "blockId": "0x9437121647899a4b7b84d67fbea7cc6ff967481c2eab4328ccd86e2cefe19420", "firstIndex": 17918066140},
|
||||||
{"blockNumber": 22234357, "blockId": "0x036030830134f9224160d5a0b62da35ec7813dc8855d554bd22e9d38545243ed", "firstIndex": 17985175075},
|
{"blockNumber": 22234357, "blockId": "0x036030830134f9224160d5a0b62da35ec7813dc8855d554bd22e9d38545243ed", "firstIndex": 17985175075},
|
||||||
{"blockNumber": 22276736, "blockId": "0x5ceb96d98aa1b4c1c2f2fa253ae9cdb1b04e0420c11bf795400e8762c0a1635c", "firstIndex": 18052284344}
|
{"blockNumber": 22276736, "blockId": "0x5ceb96d98aa1b4c1c2f2fa253ae9cdb1b04e0420c11bf795400e8762c0a1635c", "firstIndex": 18052284344},
|
||||||
|
{"blockNumber": 22321282, "blockId": "0x8a601ebf6a757020c6d43a978f0bd2c150c4acc1ffdd50c7ee88afc78b0c11f8", "firstIndex": 18119392242},
|
||||||
|
{"blockNumber": 22349231, "blockId": "0xb751c026a92ba5be95ad7ea4e2729a175b0d0e11a4c108f47cab232b4715d1a2", "firstIndex": 18186501218},
|
||||||
|
{"blockNumber": 22377469, "blockId": "0xa47916860a22f7e26761ec2d7f717410791bd3ed0237b2f6266750214c7bbf08", "firstIndex": 18253610249},
|
||||||
|
{"blockNumber": 22422685, "blockId": "0x8beaee39603af55fad222730f556c840c41cd76a5eef0bad367ac94d3b86c7aa", "firstIndex": 18320716377},
|
||||||
|
{"blockNumber": 22462378, "blockId": "0x6dba9c5d2949f5a6a072267b590e8b15e6fb157a0fc22719387f1fd6bfcd8d5d", "firstIndex": 18387828426},
|
||||||
|
{"blockNumber": 22500185, "blockId": "0x2484c380df0a8f7edfdf8d917570d23fab8499aea80c35b6cf4e5fe1e34106e9", "firstIndex": 18454936227},
|
||||||
|
{"blockNumber": 22539624, "blockId": "0xd418071906803d25afc3842a6a6468ad3b5fea27107b314ce4e2ccf08b478acf", "firstIndex": 18522044531},
|
||||||
|
{"blockNumber": 22577021, "blockId": "0xff222982693f3ff60d2097822171f80a6ddd979080aeb7e995bfb1b973497c84", "firstIndex": 18589154438},
|
||||||
|
{"blockNumber": 22614525, "blockId": "0x9868da1fea2ffca3f67e35570f02eb5707b27f6967ea4a109eb4ddbf24566efd", "firstIndex": 18656264174},
|
||||||
|
{"blockNumber": 22652848, "blockId": "0x060a911da11ab0f1dda307f5196e622d23901d198925749e70ab58a439477c5a", "firstIndex": 18723372617},
|
||||||
|
{"blockNumber": 22692432, "blockId": "0x6a937f2c283aba8c778c1f5ef340b225fd820f8a7dfa6f24f5fe541994f32f2d", "firstIndex": 18790480232},
|
||||||
|
{"blockNumber": 22731200, "blockId": "0x00d57a9e7a2dad252436fe9f0382c6a8860d301a9f9ffe6d7ac64c82b95300f8", "firstIndex": 18857590076},
|
||||||
|
{"blockNumber": 22769000, "blockId": "0xa48db20307c19c373ef2d31d85088ea14b8df0450491c31982504c87b04edbc0", "firstIndex": 18924699130},
|
||||||
|
{"blockNumber": 22808126, "blockId": "0x1419c64ff003edca0586f1c8ec3063da5c54c57ff826cfb34bc866cc18949653", "firstIndex": 18991807807},
|
||||||
|
{"blockNumber": 22845231, "blockId": "0x691f87217e61c5d7ae9ad53a44d30e1ab6b1cc3f2b689b9fbf7c38fbacacfe3e", "firstIndex": 19058917062},
|
||||||
|
{"blockNumber": 22884189, "blockId": "0x7f102d44c0ea7803f5b0e1a98a6abf0e8383eb99fb114d6f7b4591753ce8bba3", "firstIndex": 19126024122},
|
||||||
|
{"blockNumber": 22920923, "blockId": "0x04fe6179495016fc3fe56d8ef5311c360a5761a898262173849c3494fdd73d92", "firstIndex": 19193134595},
|
||||||
|
{"blockNumber": 22958100, "blockId": "0xe38e0ff7b0c4065ca42ea577bc32f2566ca46f2ddeedcc4bc1f8fb00e7f26329", "firstIndex": 19260242424},
|
||||||
|
{"blockNumber": 22988600, "blockId": "0x04ca74758b22e0ea54b8c992022ff21c16a2af9c45144c3b0f80de921a7eee82", "firstIndex": 19327351273},
|
||||||
|
{"blockNumber": 23018392, "blockId": "0x61cc979b00bc97b48356f986a5b9ec997d674bc904c2a2e4b0f17de08e50b3bb", "firstIndex": 19394459627},
|
||||||
|
{"blockNumber": 23048524, "blockId": "0x489de15d95739ede4ab15e8b5151d80d4dc85ae10e7be800b1a4723094a678df", "firstIndex": 19461570073}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,32 @@
|
||||||
{"blockNumber": 7911722, "blockId": "0x9a85e48e3135c97c51fc1786f2af0596c802e021b6c53cfca65a129cafcd23ed", "firstIndex": 4496287265},
|
{"blockNumber": 7911722, "blockId": "0x9a85e48e3135c97c51fc1786f2af0596c802e021b6c53cfca65a129cafcd23ed", "firstIndex": 4496287265},
|
||||||
{"blockNumber": 7960147, "blockId": "0xc9359cc76d7090e1c8a031108f0ab7a8935d971efd4325fe53612a1d99562f6f", "firstIndex": 4563402388},
|
{"blockNumber": 7960147, "blockId": "0xc9359cc76d7090e1c8a031108f0ab7a8935d971efd4325fe53612a1d99562f6f", "firstIndex": 4563402388},
|
||||||
{"blockNumber": 8030418, "blockId": "0x21867e68cd8327aed2da2601399d60f7f9e41dca4a4f2f9be982e5a2b9304a88", "firstIndex": 4630511616},
|
{"blockNumber": 8030418, "blockId": "0x21867e68cd8327aed2da2601399d60f7f9e41dca4a4f2f9be982e5a2b9304a88", "firstIndex": 4630511616},
|
||||||
{"blockNumber": 8087701, "blockId": "0x0fa8c8d7549cc9a8d308262706fe248efe759f8b63511efb1e7f3926e9af2dcb", "firstIndex": 4697614758}
|
{"blockNumber": 8087701, "blockId": "0x0fa8c8d7549cc9a8d308262706fe248efe759f8b63511efb1e7f3926e9af2dcb", "firstIndex": 4697614758},
|
||||||
|
{"blockNumber": 8149130, "blockId": "0x655ea638fd9e35cc25f4332f260d7bf98f4f6fa9a72e1bff861209f18659e94c", "firstIndex": 4764727744},
|
||||||
|
{"blockNumber": 8208672, "blockId": "0xb5847a670dc3b6181f9e2e40e4218548048366d237a0d12e938b9879bc8cf800", "firstIndex": 4831837882},
|
||||||
|
{"blockNumber": 8271345, "blockId": "0x96797214946f29093883b877ccb0f2a9f771a9a3db3794a642b5dcb781c4d194", "firstIndex": 4898942160},
|
||||||
|
{"blockNumber": 8302858, "blockId": "0x6a5977b3382ca69a9e0412333f97b911c1f69f857d8f31dd0fc930980e24f2fc", "firstIndex": 4966054626},
|
||||||
|
{"blockNumber": 8333618, "blockId": "0x2547294aa23b67c42adbdddfcf424b17a95c4ff0f352a6a2442c529cfb0c892a", "firstIndex": 5033163605},
|
||||||
|
{"blockNumber": 8360582, "blockId": "0xf34f5dceb0ef22e0f782b56c12790472acc675997b9c45075bd4e18a9dacd03c", "firstIndex": 5100273631},
|
||||||
|
{"blockNumber": 8387230, "blockId": "0x0fbea42e87620b5beeb76b67febc173847c54333d7dce9fa2f8f2a3fa9c8c22a", "firstIndex": 5167381673},
|
||||||
|
{"blockNumber": 8414795, "blockId": "0x6c9c000cf5e35da3a7e9e1cd56147c8ce9b43a76d6de945675efd9dc03b628c9", "firstIndex": 5234477010},
|
||||||
|
{"blockNumber": 8444749, "blockId": "0xba85f8c9abaddc34e2113eb49385667ba4b008168ae701f46aa7a7ce78c633a1", "firstIndex": 5301598562},
|
||||||
|
{"blockNumber": 8474551, "blockId": "0x720866a40242f087dd25b6f0dd79224884f435b114a39e60c5669f5c942c78c1", "firstIndex": 5368707262},
|
||||||
|
{"blockNumber": 8501310, "blockId": "0x2b6da233532c701202fb5ac67e005f7d3eb71f88a9fac10c25d24dd11ada05e5", "firstIndex": 5435803858},
|
||||||
|
{"blockNumber": 8526970, "blockId": "0x005f9bbad0a10234129d09894d7fcf04bf1398d326510eedb4195808c282802d", "firstIndex": 5502926509},
|
||||||
|
{"blockNumber": 8550412, "blockId": "0x37c9f3efc9f33cf62f590087c8c9ac70011883f75e648647a6fd0fec00ca627c", "firstIndex": 5570034950},
|
||||||
|
{"blockNumber": 8573540, "blockId": "0x81cfb46a07be7c70bb8a0f76b03a4cd502f92032bea68ad7ba10e26351673000", "firstIndex": 5637137662},
|
||||||
|
{"blockNumber": 8590416, "blockId": "0x5c223d58ef22d7b0dd8c498e8498da4787b5dc706681c2bc83849441f5d0922d", "firstIndex": 5704252906},
|
||||||
|
{"blockNumber": 8616793, "blockId": "0x9043ce02742fb5ec43a696602867b7ce6003a95b36cd28a37eeb9785a46ad49f", "firstIndex": 5771357264},
|
||||||
|
{"blockNumber": 8647290, "blockId": "0xd90115193764b0a33f3f2a719381b3ddbce2532607c72fb287a864eb391eeada", "firstIndex": 5838466144},
|
||||||
|
{"blockNumber": 8673192, "blockId": "0x9bc92d340cccaf4c8c03372efc24eb92c5159106729de8d2e9e064f5568d082b", "firstIndex": 5905577457},
|
||||||
|
{"blockNumber": 8700694, "blockId": "0xb3d656a173b962bc6825198e94a4974289db06a8998060bd0f5ee2044a7a7deb", "firstIndex": 5972679345},
|
||||||
|
{"blockNumber": 8724533, "blockId": "0x253ffc6d77b88fe18736e4c313e9930341c444bc87b2ee22b26cfe8d9d0b178d", "firstIndex": 6039795829},
|
||||||
|
{"blockNumber": 8743948, "blockId": "0x04eb66d0261705d31e629193148d0685058d7759ba5f95d2d38e412dbadb8256", "firstIndex": 6106901747},
|
||||||
|
{"blockNumber": 8758378, "blockId": "0x64adf54e662d11db716610157da672c3d8b45f001dbce40a269871b86a84d026", "firstIndex": 6174011544},
|
||||||
|
{"blockNumber": 8777722, "blockId": "0x0a7f9a956024b404c915e70b42221aa027b2dd715b0697f099dccefae0b9af97", "firstIndex": 6241124215},
|
||||||
|
{"blockNumber": 8800154, "blockId": "0x411f90dc18f2bca31fa63615c2866c907bbac1fae8c06782cabfaf788efba665", "firstIndex": 6308233216},
|
||||||
|
{"blockNumber": 8829725, "blockId": "0x5686f3a5eec1b070d0113c588f8f4a560d57ad96b8045cedb5c08bbadaa0273e", "firstIndex": 6375340033},
|
||||||
|
{"blockNumber": 8858036, "blockId": "0x4f9b5d9fac9c6f6e2224f613cda12e8ab95d636774ce87489dce8a9f805ee2e5", "firstIndex": 6442450330},
|
||||||
|
{"blockNumber": 8884811, "blockId": "0x9cf74f978872683802c065e72b5a5326fdad95f19733c34d927b575cd85fd0bd", "firstIndex": 6509559380}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -97,15 +97,15 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
|
||||||
|
|
||||||
// GetBlockNumber retrieves the block number belonging to the given hash
|
// GetBlockNumber retrieves the block number belonging to the given hash
|
||||||
// from the cache or database
|
// from the cache or database
|
||||||
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
|
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) (uint64, bool) {
|
||||||
if cached, ok := hc.numberCache.Get(hash); ok {
|
if cached, ok := hc.numberCache.Get(hash); ok {
|
||||||
return &cached
|
return cached, true
|
||||||
}
|
}
|
||||||
number := rawdb.ReadHeaderNumber(hc.chainDb, hash)
|
number, ok := rawdb.ReadHeaderNumber(hc.chainDb, hash)
|
||||||
if number != nil {
|
if ok {
|
||||||
hc.numberCache.Add(hash, *number)
|
hc.numberCache.Add(hash, number)
|
||||||
}
|
}
|
||||||
return number
|
return number, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
type headerWriteResult struct {
|
type headerWriteResult struct {
|
||||||
|
|
@ -402,11 +402,11 @@ func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header
|
||||||
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
|
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
|
||||||
// found.
|
// found.
|
||||||
func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
||||||
number := hc.GetBlockNumber(hash)
|
number, ok := hc.GetBlockNumber(hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return hc.GetHeader(hash, *number)
|
return hc.GetHeader(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasHeader checks if a block header is present in the database or not.
|
// HasHeader checks if a block header is present in the database or not.
|
||||||
|
|
|
||||||
|
|
@ -143,13 +143,13 @@ func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadHeaderNumber returns the header number assigned to a hash.
|
// ReadHeaderNumber returns the header number assigned to a hash.
|
||||||
func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 {
|
func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) (uint64, bool) {
|
||||||
data, _ := db.Get(headerNumberKey(hash))
|
data, _ := db.Get(headerNumberKey(hash))
|
||||||
if len(data) != 8 {
|
if len(data) != 8 {
|
||||||
return nil
|
return 0, false
|
||||||
}
|
}
|
||||||
number := binary.BigEndian.Uint64(data)
|
number := binary.BigEndian.Uint64(data)
|
||||||
return &number
|
return number, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteHeaderNumber stores the hash->number mapping.
|
// WriteHeaderNumber stores the hash->number mapping.
|
||||||
|
|
@ -935,11 +935,11 @@ func ReadHeadHeader(db ethdb.Reader) *types.Header {
|
||||||
if headHeaderHash == (common.Hash{}) {
|
if headHeaderHash == (common.Hash{}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
headHeaderNumber := ReadHeaderNumber(db, headHeaderHash)
|
headHeaderNumber, ok := ReadHeaderNumber(db, headHeaderHash)
|
||||||
if headHeaderNumber == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ReadHeader(db, headHeaderHash, *headHeaderNumber)
|
return ReadHeader(db, headHeaderHash, headHeaderNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadHeadBlock returns the current canonical head block.
|
// ReadHeadBlock returns the current canonical head block.
|
||||||
|
|
@ -948,9 +948,9 @@ func ReadHeadBlock(db ethdb.Reader) *types.Block {
|
||||||
if headBlockHash == (common.Hash{}) {
|
if headBlockHash == (common.Hash{}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
headBlockNumber := ReadHeaderNumber(db, headBlockHash)
|
headBlockNumber, ok := ReadHeaderNumber(db, headBlockHash)
|
||||||
if headBlockNumber == nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ReadBlock(db, headBlockHash, *headBlockNumber)
|
return ReadBlock(db, headBlockHash, headBlockNumber)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,11 @@ func DecodeTxLookupEntry(data []byte, db ethdb.Reader) *uint64 {
|
||||||
}
|
}
|
||||||
// Database v4-v5 tx lookup format just stores the hash
|
// Database v4-v5 tx lookup format just stores the hash
|
||||||
if len(data) == common.HashLength {
|
if len(data) == common.HashLength {
|
||||||
return ReadHeaderNumber(db, common.BytesToHash(data))
|
number, ok := ReadHeaderNumber(db, common.BytesToHash(data))
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &number
|
||||||
}
|
}
|
||||||
// Finally try database v3 tx lookup format
|
// Finally try database v3 tx lookup format
|
||||||
var entry LegacyTxLookupEntry
|
var entry LegacyTxLookupEntry
|
||||||
|
|
|
||||||
|
|
@ -157,14 +157,6 @@ func WriteTrieJournal(db ethdb.KeyValueWriter, journal []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTrieJournal deletes the serialized in-memory trie nodes of layers saved at
|
|
||||||
// the last shutdown.
|
|
||||||
func DeleteTrieJournal(db ethdb.KeyValueWriter) {
|
|
||||||
if err := db.Delete(trieJournalKey); err != nil {
|
|
||||||
log.Crit("Failed to remove tries journal", "err", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadStateHistoryMeta retrieves the metadata corresponding to the specified
|
// ReadStateHistoryMeta retrieves the metadata corresponding to the specified
|
||||||
// state history. Compute the position of state history in freezer by minus
|
// state history. Compute the position of state history in freezer by minus
|
||||||
// one since the id of first state history starts from one(zero for initial
|
// one since the id of first state history starts from one(zero for initial
|
||||||
|
|
|
||||||
|
|
@ -104,15 +104,15 @@ func (f *chainFreezer) Close() error {
|
||||||
func (f *chainFreezer) readHeadNumber(db ethdb.KeyValueReader) uint64 {
|
func (f *chainFreezer) readHeadNumber(db ethdb.KeyValueReader) uint64 {
|
||||||
hash := ReadHeadBlockHash(db)
|
hash := ReadHeadBlockHash(db)
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
log.Error("Head block is not reachable")
|
log.Warn("Head block is not reachable")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
number := ReadHeaderNumber(db, hash)
|
number, ok := ReadHeaderNumber(db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
log.Error("Number of head block is missing")
|
log.Error("Number of head block is missing")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return *number
|
return number
|
||||||
}
|
}
|
||||||
|
|
||||||
// readFinalizedNumber returns the number of finalized block. 0 is returned
|
// readFinalizedNumber returns the number of finalized block. 0 is returned
|
||||||
|
|
@ -122,12 +122,12 @@ func (f *chainFreezer) readFinalizedNumber(db ethdb.KeyValueReader) uint64 {
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
number := ReadHeaderNumber(db, hash)
|
number, ok := ReadHeaderNumber(db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
log.Error("Number of finalized block is missing")
|
log.Error("Number of finalized block is missing")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return *number
|
return number
|
||||||
}
|
}
|
||||||
|
|
||||||
// freezeThreshold returns the threshold for chain freezing. It's determined
|
// freezeThreshold returns the threshold for chain freezing. It's determined
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,12 @@ func Open(db ethdb.KeyValueStore, opts OpenOptions) (ethdb.Database, error) {
|
||||||
if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
|
if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
|
||||||
// Subsequent header after the freezer limit is missing from the database.
|
// Subsequent header after the freezer limit is missing from the database.
|
||||||
// Reject startup if the database has a more recent head.
|
// Reject startup if the database has a more recent head.
|
||||||
if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 {
|
head, ok := ReadHeaderNumber(db, ReadHeadHeaderHash(db))
|
||||||
|
if !ok {
|
||||||
|
printChainMetadata(db)
|
||||||
|
return nil, fmt.Errorf("could not read header number, hash %v", ReadHeadHeaderHash(db))
|
||||||
|
}
|
||||||
|
if head > frozen-1 {
|
||||||
// Find the smallest block stored in the key-value store
|
// Find the smallest block stored in the key-value store
|
||||||
// in range of [frozen, head]
|
// in range of [frozen, head]
|
||||||
var number uint64
|
var number uint64
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,16 @@ import (
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the maximum amount of data that will be buffered in memory
|
const (
|
||||||
// for a single freezer table batch.
|
// This is the maximum amount of data that will be buffered in memory
|
||||||
const freezerBatchBufferLimit = 2 * 1024 * 1024
|
// for a single freezer table batch.
|
||||||
|
freezerBatchBufferLimit = 2 * 1024 * 1024
|
||||||
|
|
||||||
|
// freezerTableFlushThreshold defines the threshold for triggering a freezer
|
||||||
|
// table sync operation. If the number of accumulated uncommitted items exceeds
|
||||||
|
// this value, a sync will be scheduled.
|
||||||
|
freezerTableFlushThreshold = 512
|
||||||
|
)
|
||||||
|
|
||||||
// freezerBatch is a write operation of multiple items on a freezer.
|
// freezerBatch is a write operation of multiple items on a freezer.
|
||||||
type freezerBatch struct {
|
type freezerBatch struct {
|
||||||
|
|
@ -201,6 +208,7 @@ func (batch *freezerTableBatch) commit() error {
|
||||||
|
|
||||||
// Update headBytes of table.
|
// Update headBytes of table.
|
||||||
batch.t.headBytes += dataSize
|
batch.t.headBytes += dataSize
|
||||||
|
items := batch.curItem - batch.t.items.Load()
|
||||||
batch.t.items.Store(batch.curItem)
|
batch.t.items.Store(batch.curItem)
|
||||||
|
|
||||||
// Update metrics.
|
// Update metrics.
|
||||||
|
|
@ -208,7 +216,9 @@ func (batch *freezerTableBatch) commit() error {
|
||||||
batch.t.writeMeter.Mark(dataSize + indexSize)
|
batch.t.writeMeter.Mark(dataSize + indexSize)
|
||||||
|
|
||||||
// Periodically sync the table, todo (rjl493456442) make it configurable?
|
// Periodically sync the table, todo (rjl493456442) make it configurable?
|
||||||
if time.Since(batch.t.lastSync) > 30*time.Second {
|
batch.t.uncommitted += items
|
||||||
|
if batch.t.uncommitted > freezerTableFlushThreshold && time.Since(batch.t.lastSync) > 30*time.Second {
|
||||||
|
batch.t.uncommitted = 0
|
||||||
batch.t.lastSync = time.Now()
|
batch.t.lastSync = time.Now()
|
||||||
return batch.t.Sync()
|
return batch.t.Sync()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,9 @@ type freezerTable struct {
|
||||||
headId uint32 // number of the currently active head file
|
headId uint32 // number of the currently active head file
|
||||||
tailId uint32 // number of the earliest file
|
tailId uint32 // number of the earliest file
|
||||||
|
|
||||||
metadata *freezerTableMeta // metadata of the table
|
metadata *freezerTableMeta // metadata of the table
|
||||||
lastSync time.Time // Timestamp when the last sync was performed
|
uncommitted uint64 // Count of items written without flushing to file
|
||||||
|
lastSync time.Time // Timestamp when the last sync was performed
|
||||||
|
|
||||||
headBytes int64 // Number of bytes written to the head file
|
headBytes int64 // Number of bytes written to the head file
|
||||||
readMeter *metrics.Meter // Meter for measuring the effective amount of data read
|
readMeter *metrics.Meter // Meter for measuring the effective amount of data read
|
||||||
|
|
|
||||||
|
|
@ -145,10 +145,7 @@ func (al *accessList) Equal(other *accessList) bool {
|
||||||
// PrettyPrint prints the contents of the access list in a human-readable form
|
// PrettyPrint prints the contents of the access list in a human-readable form
|
||||||
func (al *accessList) PrettyPrint() string {
|
func (al *accessList) PrettyPrint() string {
|
||||||
out := new(strings.Builder)
|
out := new(strings.Builder)
|
||||||
var sortedAddrs []common.Address
|
sortedAddrs := slices.Collect(maps.Keys(al.addresses))
|
||||||
for addr := range al.addresses {
|
|
||||||
sortedAddrs = append(sortedAddrs, addr)
|
|
||||||
}
|
|
||||||
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
||||||
for _, addr := range sortedAddrs {
|
for _, addr := range sortedAddrs {
|
||||||
idx := al.addresses[addr]
|
idx := al.addresses[addr]
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ func iterateJournal(db ethdb.KeyValueReader, callback journalCallback) error {
|
||||||
}
|
}
|
||||||
if len(destructs) > 0 {
|
if len(destructs) > 0 {
|
||||||
log.Warn("Incompatible legacy journal detected", "version", journalV0)
|
log.Warn("Incompatible legacy journal detected", "version", journalV0)
|
||||||
return fmt.Errorf("incompatible legacy journal detected")
|
return errors.New("incompatible legacy journal detected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := r.Decode(&accounts); err != nil {
|
if err := r.Decode(&accounts); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ func (s *StateDB) GetLogs(hash common.Hash, blockNumber uint64, blockHash common
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) Logs() []*types.Log {
|
func (s *StateDB) Logs() []*types.Log {
|
||||||
var logs []*types.Log
|
logs := make([]*types.Log, 0, s.logSize)
|
||||||
for _, lgs := range s.logs {
|
for _, lgs := range s.logs {
|
||||||
logs = append(logs, lgs...)
|
logs = append(logs, lgs...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -70,19 +71,13 @@ func (t transientStorage) Copy() transientStorage {
|
||||||
// PrettyPrint prints the contents of the access list in a human-readable form
|
// PrettyPrint prints the contents of the access list in a human-readable form
|
||||||
func (t transientStorage) PrettyPrint() string {
|
func (t transientStorage) PrettyPrint() string {
|
||||||
out := new(strings.Builder)
|
out := new(strings.Builder)
|
||||||
var sortedAddrs []common.Address
|
sortedAddrs := slices.Collect(maps.Keys(t))
|
||||||
for addr := range t {
|
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
||||||
sortedAddrs = append(sortedAddrs, addr)
|
|
||||||
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range sortedAddrs {
|
for _, addr := range sortedAddrs {
|
||||||
fmt.Fprintf(out, "%#x:", addr)
|
fmt.Fprintf(out, "%#x:", addr)
|
||||||
var sortedKeys []common.Hash
|
|
||||||
storage := t[addr]
|
storage := t[addr]
|
||||||
for key := range storage {
|
sortedKeys := slices.Collect(maps.Keys(storage))
|
||||||
sortedKeys = append(sortedKeys, key)
|
|
||||||
}
|
|
||||||
slices.SortFunc(sortedKeys, common.Hash.Cmp)
|
slices.SortFunc(sortedKeys, common.Hash.Cmp)
|
||||||
for _, key := range sortedKeys {
|
for _, key := range sortedKeys {
|
||||||
fmt.Fprintf(out, " %X : %X\n", key, storage[key])
|
fmt.Fprintf(out, " %X : %X\n", key, storage[key])
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes())
|
bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes())
|
||||||
tooBigNumber := new(big.Int).Set(bigNumber)
|
tooBigNumber := new(big.Int).Set(bigNumber)
|
||||||
tooBigNumber.Add(tooBigNumber, common.Big1)
|
tooBigNumber.Add(tooBigNumber, common.Big1)
|
||||||
|
gasLimit := blockchain.CurrentHeader().GasLimit
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
txs []*types.Transaction
|
txs []*types.Transaction
|
||||||
want string
|
want string
|
||||||
|
|
@ -157,9 +158,9 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
{ // ErrGasLimitReached
|
{ // ErrGasLimitReached
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), gasLimit+1, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
want: "could not apply tx 0 [0xd0fb3ea181e800cd55c4637c55c1f2f78137efb6bb9723e50bda3cad97208db2]: gas limit reached",
|
||||||
},
|
},
|
||||||
{ // ErrInsufficientFundsForTransfer
|
{ // ErrInsufficientFundsForTransfer
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
|
|
@ -185,9 +186,9 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
{ // ErrGasLimitReached
|
{ // ErrGasLimitReached
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), gasLimit+1, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
want: "could not apply tx 0 [0xd0fb3ea181e800cd55c4637c55c1f2f78137efb6bb9723e50bda3cad97208db2]: gas limit reached",
|
||||||
},
|
},
|
||||||
{ // ErrFeeCapTooLow
|
{ // ErrFeeCapTooLow
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
|
|
@ -256,6 +257,12 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
// ErrSetCodeTxCreate cannot be tested here: it is impossible to create a SetCode-tx with nil `to`.
|
// ErrSetCodeTxCreate cannot be tested here: it is impossible to create a SetCode-tx with nil `to`.
|
||||||
// The EstimateGas API tests test this case.
|
// The EstimateGas API tests test this case.
|
||||||
|
{ // ErrGasLimitTooHigh
|
||||||
|
txs: []*types.Transaction{
|
||||||
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.MaxTxGas+1, big.NewInt(875000000), nil),
|
||||||
|
},
|
||||||
|
want: "could not apply tx 0 [0x16505812a6da0b0150593e4d4eb90190ba64816a04b27d19ca926ebd6aff8aa0]: transaction gas limit too high (cap: 16777216, tx: 16777217)",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false)
|
block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false)
|
||||||
_, err := blockchain.InsertChain(types.Blocks{block})
|
_, err := blockchain.InsertChain(types.Blocks{block})
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,7 @@ func (st *stateTransition) preCheck() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check the blob version validity
|
// Check the blob version validity
|
||||||
|
isOsaka := st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time)
|
||||||
if msg.BlobHashes != nil {
|
if msg.BlobHashes != nil {
|
||||||
// The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally
|
// The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally
|
||||||
// has it as a non-nillable value, so any msg derived from blob transaction has it non-nil.
|
// has it as a non-nillable value, so any msg derived from blob transaction has it non-nil.
|
||||||
|
|
@ -364,6 +365,9 @@ func (st *stateTransition) preCheck() error {
|
||||||
if len(msg.BlobHashes) == 0 {
|
if len(msg.BlobHashes) == 0 {
|
||||||
return ErrMissingBlobHashes
|
return ErrMissingBlobHashes
|
||||||
}
|
}
|
||||||
|
if isOsaka && len(msg.BlobHashes) > params.BlobTxMaxBlobs {
|
||||||
|
return ErrTooManyBlobs
|
||||||
|
}
|
||||||
for i, hash := range msg.BlobHashes {
|
for i, hash := range msg.BlobHashes {
|
||||||
if !kzg4844.IsValidVersionedHash(hash[:]) {
|
if !kzg4844.IsValidVersionedHash(hash[:]) {
|
||||||
return fmt.Errorf("blob %d has invalid hash version", i)
|
return fmt.Errorf("blob %d has invalid hash version", i)
|
||||||
|
|
@ -395,7 +399,7 @@ func (st *stateTransition) preCheck() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify tx gas limit does not exceed EIP-7825 cap.
|
// Verify tx gas limit does not exceed EIP-7825 cap.
|
||||||
if st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time) && msg.GasLimit > params.MaxTxGas {
|
if isOsaka && msg.GasLimit > params.MaxTxGas {
|
||||||
return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
|
return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
|
||||||
}
|
}
|
||||||
return st.buyGas()
|
return st.buyGas()
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
package tracing
|
package tracing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -39,14 +39,14 @@ type entry interface {
|
||||||
// WrapWithJournal wraps the given tracer with a journaling layer.
|
// WrapWithJournal wraps the given tracer with a journaling layer.
|
||||||
func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
||||||
if hooks == nil {
|
if hooks == nil {
|
||||||
return nil, fmt.Errorf("wrapping nil tracer")
|
return nil, errors.New("wrapping nil tracer")
|
||||||
}
|
}
|
||||||
// No state change to journal, return the wrapped hooks as is
|
// No state change to journal, return the wrapped hooks as is
|
||||||
if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil {
|
if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil {
|
||||||
return hooks, nil
|
return hooks, nil
|
||||||
}
|
}
|
||||||
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
|
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
|
||||||
return nil, fmt.Errorf("cannot have both OnNonceChange and OnNonceChangeV2")
|
return nil, errors.New("cannot have both OnNonceChange and OnNonceChangeV2")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Hooks instance and copy all hooks
|
// Create a new Hooks instance and copy all hooks
|
||||||
|
|
|
||||||
|
|
@ -217,11 +217,11 @@ func (indexer *txIndexer) resolveHead() uint64 {
|
||||||
if headBlockHash == (common.Hash{}) {
|
if headBlockHash == (common.Hash{}) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
headBlockNumber := rawdb.ReadHeaderNumber(indexer.db, headBlockHash)
|
headBlockNumber, ok := rawdb.ReadHeaderNumber(indexer.db, headBlockHash)
|
||||||
if headBlockNumber == nil {
|
if !ok {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return *headBlockNumber
|
return headBlockNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending
|
// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ const (
|
||||||
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
|
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
|
||||||
// in order to ensure network and txpool stability.
|
// in order to ensure network and txpool stability.
|
||||||
// Note: if you increase this, validation will fail on txMaxSize.
|
// Note: if you increase this, validation will fail on txMaxSize.
|
||||||
maxBlobsPerTx = 7
|
maxBlobsPerTx = params.BlobTxMaxBlobs
|
||||||
|
|
||||||
// maxTxsPerAccount is the maximum number of blob transactions admitted from
|
// maxTxsPerAccount is the maximum number of blob transactions admitted from
|
||||||
// a single account. The limit is enforced to minimize the DoS potential of
|
// a single account. The limit is enforced to minimize the DoS potential of
|
||||||
|
|
@ -326,10 +326,6 @@ type BlobPool struct {
|
||||||
discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded)
|
discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded)
|
||||||
insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included)
|
insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included)
|
||||||
|
|
||||||
// txValidationFn defaults to txpool.ValidateTransaction, but can be
|
|
||||||
// overridden for testing purposes.
|
|
||||||
txValidationFn txpool.ValidationFunction
|
|
||||||
|
|
||||||
lock sync.RWMutex // Mutex protecting the pool during reorg handling
|
lock sync.RWMutex // Mutex protecting the pool during reorg handling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,7 +344,6 @@ func New(config Config, chain BlockChain, hasPendingAuth func(common.Address) bo
|
||||||
lookup: newLookup(),
|
lookup: newLookup(),
|
||||||
index: make(map[common.Address][]*blobTxMeta),
|
index: make(map[common.Address][]*blobTxMeta),
|
||||||
spent: make(map[common.Address]*uint256.Int),
|
spent: make(map[common.Address]*uint256.Int),
|
||||||
txValidationFn: txpool.ValidateTransaction,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,11 +238,7 @@ func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCa
|
||||||
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
||||||
BlobHashes: blobHashes,
|
BlobHashes: blobHashes,
|
||||||
Value: uint256.NewInt(100),
|
Value: uint256.NewInt(100),
|
||||||
Sidecar: &types.BlobTxSidecar{
|
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion0, blobs, commitments, proofs),
|
||||||
Blobs: blobs,
|
|
||||||
Commitments: commitments,
|
|
||||||
Proofs: proofs,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
||||||
}
|
}
|
||||||
|
|
@ -265,11 +261,7 @@ func makeUnsignedTxWithTestBlob(nonce uint64, gasTipCap uint64, gasFeeCap uint64
|
||||||
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
||||||
BlobHashes: []common.Hash{testBlobVHashes[blobIdx]},
|
BlobHashes: []common.Hash{testBlobVHashes[blobIdx]},
|
||||||
Value: uint256.NewInt(100),
|
Value: uint256.NewInt(100),
|
||||||
Sidecar: &types.BlobTxSidecar{
|
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion0, []kzg4844.Blob{*testBlobs[blobIdx]}, []kzg4844.Commitment{testBlobCommits[blobIdx]}, []kzg4844.Proof{testBlobProofs[blobIdx]}),
|
||||||
Blobs: []kzg4844.Blob{*testBlobs[blobIdx]},
|
|
||||||
Commitments: []kzg4844.Commitment{testBlobCommits[blobIdx]},
|
|
||||||
Proofs: []kzg4844.Proof{testBlobProofs[blobIdx]},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1199,8 +1191,8 @@ func TestBlobCountLimit(t *testing.T) {
|
||||||
|
|
||||||
// Attempt to add transactions.
|
// Attempt to add transactions.
|
||||||
var (
|
var (
|
||||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 7, key1)
|
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, key1)
|
||||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 8, key2)
|
tx2 = makeMultiBlobTx(0, 1, 800, 70, 7, key2)
|
||||||
)
|
)
|
||||||
errs := pool.Add([]*types.Transaction{tx1, tx2}, true)
|
errs := pool.Add([]*types.Transaction{tx1, tx2}, true)
|
||||||
|
|
||||||
|
|
@ -1732,12 +1724,6 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) {
|
||||||
// Make the pool not use disk (just drop everything). This test never reads
|
// Make the pool not use disk (just drop everything). This test never reads
|
||||||
// back the data, it just iterates over the pool in-memory items
|
// back the data, it just iterates over the pool in-memory items
|
||||||
pool.store = &fakeBilly{pool.store, 0}
|
pool.store = &fakeBilly{pool.store, 0}
|
||||||
// Avoid validation - verifying all blob proofs take significant time
|
|
||||||
// when the capacity is large. The purpose of this bench is to measure assembling
|
|
||||||
// the lazies, not the kzg verifications.
|
|
||||||
pool.txValidationFn = func(tx *types.Transaction, head *types.Header, signer types.Signer, opts *txpool.ValidationOptions) error {
|
|
||||||
return nil // accept all
|
|
||||||
}
|
|
||||||
// Fill the pool up with one random transaction from each account with the
|
// Fill the pool up with one random transaction from each account with the
|
||||||
// same price and everything to maximize the worst case scenario
|
// same price and everything to maximize the worst case scenario
|
||||||
for i := 0; i < int(capacity); i++ {
|
for i := 0; i < int(capacity); i++ {
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
||||||
}
|
}
|
||||||
if tx.Type() == types.SetCodeTxType {
|
if tx.Type() == types.SetCodeTxType {
|
||||||
if len(tx.SetCodeAuthorizations()) == 0 {
|
if len(tx.SetCodeAuthorizations()) == 0 {
|
||||||
return fmt.Errorf("set code tx must have at least one authorization tuple")
|
return errors.New("set code tx must have at least one authorization tuple")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -185,7 +185,7 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
||||||
if sidecar.Version != 0 {
|
if sidecar.Version != types.BlobSidecarVersion0 {
|
||||||
return fmt.Errorf("invalid sidecar version pre-osaka: %v", sidecar.Version)
|
return fmt.Errorf("invalid sidecar version pre-osaka: %v", sidecar.Version)
|
||||||
}
|
}
|
||||||
if len(sidecar.Proofs) != len(hashes) {
|
if len(sidecar.Proofs) != len(hashes) {
|
||||||
|
|
@ -200,7 +200,7 @@ func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Has
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateBlobSidecarOsaka(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
func validateBlobSidecarOsaka(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
||||||
if sidecar.Version != 1 {
|
if sidecar.Version != types.BlobSidecarVersion1 {
|
||||||
return fmt.Errorf("invalid sidecar version post-osaka: %v", sidecar.Version)
|
return fmt.Errorf("invalid sidecar version post-osaka: %v", sidecar.Version)
|
||||||
}
|
}
|
||||||
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
|
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
|
||||||
|
|
|
||||||
182
core/types/bal/bal.go
Normal file
182
core/types/bal/bal.go
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
// Copyright 2025 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 bal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"maps"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CodeChange contains the runtime bytecode deployed at an address and the
|
||||||
|
// transaction index where the deployment took place.
|
||||||
|
type CodeChange struct {
|
||||||
|
TxIndex uint16
|
||||||
|
Code []byte `json:"code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstructionAccountAccess contains post-block account state for mutations as well as
|
||||||
|
// all storage keys that were read during execution. It is used when building block
|
||||||
|
// access list during execution.
|
||||||
|
type ConstructionAccountAccess struct {
|
||||||
|
// StorageWrites is the post-state values of an account's storage slots
|
||||||
|
// that were modified in a block, keyed by the slot key and the tx index
|
||||||
|
// where the modification occurred.
|
||||||
|
StorageWrites map[common.Hash]map[uint16]common.Hash `json:"storageWrites,omitempty"`
|
||||||
|
|
||||||
|
// StorageReads is the set of slot keys that were accessed during block
|
||||||
|
// execution.
|
||||||
|
//
|
||||||
|
// Storage slots which are both read and written (with changed values)
|
||||||
|
// appear only in StorageWrites.
|
||||||
|
StorageReads map[common.Hash]struct{} `json:"storageReads,omitempty"`
|
||||||
|
|
||||||
|
// BalanceChanges contains the post-transaction balances of an account,
|
||||||
|
// keyed by transaction indices where it was changed.
|
||||||
|
BalanceChanges map[uint16]*uint256.Int `json:"balanceChanges,omitempty"`
|
||||||
|
|
||||||
|
// NonceChanges contains the post-state nonce values of an account keyed
|
||||||
|
// by tx index.
|
||||||
|
NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"`
|
||||||
|
|
||||||
|
// CodeChange is only set for contract accounts which were deployed in
|
||||||
|
// the block.
|
||||||
|
CodeChange *CodeChange `json:"codeChange,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConstructionAccountAccess initializes the account access object.
|
||||||
|
func NewConstructionAccountAccess() *ConstructionAccountAccess {
|
||||||
|
return &ConstructionAccountAccess{
|
||||||
|
StorageWrites: make(map[common.Hash]map[uint16]common.Hash),
|
||||||
|
StorageReads: make(map[common.Hash]struct{}),
|
||||||
|
BalanceChanges: make(map[uint16]*uint256.Int),
|
||||||
|
NonceChanges: make(map[uint16]uint64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstructionBlockAccessList contains post-block modified state and some state accessed
|
||||||
|
// in execution (account addresses and storage keys).
|
||||||
|
type ConstructionBlockAccessList struct {
|
||||||
|
Accounts map[common.Address]*ConstructionAccountAccess
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConstructionBlockAccessList instantiates an empty access list.
|
||||||
|
func NewConstructionBlockAccessList() ConstructionBlockAccessList {
|
||||||
|
return ConstructionBlockAccessList{
|
||||||
|
Accounts: make(map[common.Address]*ConstructionAccountAccess),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountRead records the address of an account that has been read during execution.
|
||||||
|
func (b *ConstructionBlockAccessList) AccountRead(addr common.Address) {
|
||||||
|
if _, ok := b.Accounts[addr]; !ok {
|
||||||
|
b.Accounts[addr] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageRead records a storage key read during execution.
|
||||||
|
func (b *ConstructionBlockAccessList) StorageRead(address common.Address, key common.Hash) {
|
||||||
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
if _, ok := b.Accounts[address].StorageWrites[key]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.Accounts[address].StorageReads[key] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageWrite records the post-transaction value of a mutated storage slot.
|
||||||
|
// The storage slot is removed from the list of read slots.
|
||||||
|
func (b *ConstructionBlockAccessList) StorageWrite(txIdx uint16, address common.Address, key, value common.Hash) {
|
||||||
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
if _, ok := b.Accounts[address].StorageWrites[key]; !ok {
|
||||||
|
b.Accounts[address].StorageWrites[key] = make(map[uint16]common.Hash)
|
||||||
|
}
|
||||||
|
b.Accounts[address].StorageWrites[key][txIdx] = value
|
||||||
|
|
||||||
|
delete(b.Accounts[address].StorageReads, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodeChange records the code of a newly-created contract.
|
||||||
|
func (b *ConstructionBlockAccessList) CodeChange(address common.Address, txIndex uint16, code []byte) {
|
||||||
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
b.Accounts[address].CodeChange = &CodeChange{
|
||||||
|
TxIndex: txIndex,
|
||||||
|
Code: bytes.Clone(code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NonceChange records tx post-state nonce of any contract-like accounts whose
|
||||||
|
// nonce was incremented.
|
||||||
|
func (b *ConstructionBlockAccessList) NonceChange(address common.Address, txIdx uint16, postNonce uint64) {
|
||||||
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
b.Accounts[address].NonceChanges[txIdx] = postNonce
|
||||||
|
}
|
||||||
|
|
||||||
|
// BalanceChange records the post-transaction balance of an account whose
|
||||||
|
// balance changed.
|
||||||
|
func (b *ConstructionBlockAccessList) BalanceChange(txIdx uint16, address common.Address, balance *uint256.Int) {
|
||||||
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
|
}
|
||||||
|
b.Accounts[address].BalanceChanges[txIdx] = balance.Clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrettyPrint returns a human-readable representation of the access list
|
||||||
|
func (b *ConstructionBlockAccessList) PrettyPrint() string {
|
||||||
|
enc := b.toEncodingObj()
|
||||||
|
return enc.PrettyPrint()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the access list.
|
||||||
|
func (b *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
|
||||||
|
res := NewConstructionBlockAccessList()
|
||||||
|
for addr, aa := range b.Accounts {
|
||||||
|
var aaCopy ConstructionAccountAccess
|
||||||
|
|
||||||
|
slotWrites := make(map[common.Hash]map[uint16]common.Hash, len(aa.StorageWrites))
|
||||||
|
for key, m := range aa.StorageWrites {
|
||||||
|
slotWrites[key] = maps.Clone(m)
|
||||||
|
}
|
||||||
|
aaCopy.StorageWrites = slotWrites
|
||||||
|
aaCopy.StorageReads = maps.Clone(aa.StorageReads)
|
||||||
|
|
||||||
|
balances := make(map[uint16]*uint256.Int, len(aa.BalanceChanges))
|
||||||
|
for index, balance := range aa.BalanceChanges {
|
||||||
|
balances[index] = balance.Clone()
|
||||||
|
}
|
||||||
|
aaCopy.BalanceChanges = balances
|
||||||
|
aaCopy.NonceChanges = maps.Clone(aa.NonceChanges)
|
||||||
|
|
||||||
|
if aa.CodeChange != nil {
|
||||||
|
aaCopy.CodeChange = &CodeChange{
|
||||||
|
TxIndex: aa.CodeChange.TxIndex,
|
||||||
|
Code: bytes.Clone(aa.CodeChange.Code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.Accounts[addr] = &aaCopy
|
||||||
|
}
|
||||||
|
return &res
|
||||||
|
}
|
||||||
344
core/types/bal/bal_encoding.go
Normal file
344
core/types/bal/bal_encoding.go
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
// Copyright 2025 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 bal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"cmp"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"maps"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_generated.go -type BlockAccessList -decoder
|
||||||
|
|
||||||
|
// These are objects used as input for the access list encoding. They mirror
|
||||||
|
// the spec format.
|
||||||
|
|
||||||
|
// BlockAccessList is the encoding format of ConstructionBlockAccessList.
|
||||||
|
type BlockAccessList struct {
|
||||||
|
Accesses []AccountAccess `ssz-max:"300000"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate returns an error if the contents of the access list are not ordered
|
||||||
|
// according to the spec or any code changes are contained which exceed protocol
|
||||||
|
// max code size.
|
||||||
|
func (e *BlockAccessList) Validate() error {
|
||||||
|
if !slices.IsSortedFunc(e.Accesses, func(a, b AccountAccess) int {
|
||||||
|
return bytes.Compare(a.Address[:], b.Address[:])
|
||||||
|
}) {
|
||||||
|
return errors.New("block access list accounts not in lexicographic order")
|
||||||
|
}
|
||||||
|
for _, entry := range e.Accesses {
|
||||||
|
if err := entry.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash computes the keccak256 hash of the access list
|
||||||
|
func (e *BlockAccessList) Hash() common.Hash {
|
||||||
|
var enc bytes.Buffer
|
||||||
|
err := e.EncodeRLP(&enc)
|
||||||
|
if err != nil {
|
||||||
|
// errors here are related to BAL values exceeding maximum size defined
|
||||||
|
// by the spec. Hard-fail because these cases are not expected to be hit
|
||||||
|
// under reasonable conditions.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return crypto.Keccak256Hash(enc.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeBalance encodes the provided balance into 16-bytes.
|
||||||
|
func encodeBalance(val *uint256.Int) [16]byte {
|
||||||
|
valBytes := val.Bytes()
|
||||||
|
if len(valBytes) > 16 {
|
||||||
|
panic("can't encode value that is greater than 16 bytes in size")
|
||||||
|
}
|
||||||
|
var enc [16]byte
|
||||||
|
copy(enc[16-len(valBytes):], valBytes[:])
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodingBalanceChange is the encoding format of BalanceChange.
|
||||||
|
type encodingBalanceChange struct {
|
||||||
|
TxIdx uint16 `ssz-size:"2"`
|
||||||
|
Balance [16]byte `ssz-size:"16"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodingAccountNonce is the encoding format of NonceChange.
|
||||||
|
type encodingAccountNonce struct {
|
||||||
|
TxIdx uint16 `ssz-size:"2"`
|
||||||
|
Nonce uint64 `ssz-size:"8"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodingStorageWrite is the encoding format of StorageWrites.
|
||||||
|
type encodingStorageWrite struct {
|
||||||
|
TxIdx uint16
|
||||||
|
ValueAfter [32]byte `ssz-size:"32"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodingStorageWrite is the encoding format of SlotWrites.
|
||||||
|
type encodingSlotWrites struct {
|
||||||
|
Slot [32]byte `ssz-size:"32"`
|
||||||
|
Accesses []encodingStorageWrite `ssz-max:"300000"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate returns an instance of the encoding-representation slot writes in
|
||||||
|
// working representation.
|
||||||
|
func (e *encodingSlotWrites) validate() error {
|
||||||
|
if slices.IsSortedFunc(e.Accesses, func(a, b encodingStorageWrite) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("storage write tx indices not in order")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountAccess is the encoding format of ConstructionAccountAccess.
|
||||||
|
type AccountAccess struct {
|
||||||
|
Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address
|
||||||
|
StorageWrites []encodingSlotWrites `ssz-max:"300000"` // Storage changes (slot -> [tx_index -> new_value])
|
||||||
|
StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys
|
||||||
|
BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance])
|
||||||
|
NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce])
|
||||||
|
Code []CodeChange `ssz-max:"1"` // Code changes ([tx_index -> new_code])
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate converts the account accesses out of encoding format.
|
||||||
|
// If any of the keys in the encoding object are not ordered according to the
|
||||||
|
// spec, an error is returned.
|
||||||
|
func (e *AccountAccess) validate() error {
|
||||||
|
// Check the storage write slots are sorted in order
|
||||||
|
if !slices.IsSortedFunc(e.StorageWrites, func(a, b encodingSlotWrites) int {
|
||||||
|
return bytes.Compare(a.Slot[:], b.Slot[:])
|
||||||
|
}) {
|
||||||
|
return errors.New("storage writes slots not in lexicographic order")
|
||||||
|
}
|
||||||
|
for _, write := range e.StorageWrites {
|
||||||
|
if err := write.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the storage read slots are sorted in order
|
||||||
|
if !slices.IsSortedFunc(e.StorageReads, func(a, b [32]byte) int {
|
||||||
|
return bytes.Compare(a[:], b[:])
|
||||||
|
}) {
|
||||||
|
return errors.New("storage read slots not in lexicographic order")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the balance changes are sorted in order
|
||||||
|
if !slices.IsSortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
}) {
|
||||||
|
return errors.New("balance changes not in ascending order by tx index")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the nonce changes are sorted in order
|
||||||
|
if !slices.IsSortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
}) {
|
||||||
|
return errors.New("nonce changes not in ascending order by tx index")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert code change
|
||||||
|
if len(e.Code) == 1 {
|
||||||
|
if len(e.Code[0].Code) > params.MaxCodeSize {
|
||||||
|
return errors.New("code change contained oversized code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the account access
|
||||||
|
func (e *AccountAccess) Copy() AccountAccess {
|
||||||
|
res := AccountAccess{
|
||||||
|
Address: e.Address,
|
||||||
|
StorageReads: slices.Clone(e.StorageReads),
|
||||||
|
BalanceChanges: slices.Clone(e.BalanceChanges),
|
||||||
|
NonceChanges: slices.Clone(e.NonceChanges),
|
||||||
|
}
|
||||||
|
for _, storageWrite := range e.StorageWrites {
|
||||||
|
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
||||||
|
Slot: storageWrite.Slot,
|
||||||
|
Accesses: slices.Clone(storageWrite.Accesses),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(e.Code) == 1 {
|
||||||
|
res.Code = []CodeChange{
|
||||||
|
{
|
||||||
|
e.Code[0].TxIndex,
|
||||||
|
bytes.Clone(e.Code[0].Code),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRLP returns the RLP-encoded access list
|
||||||
|
func (b *ConstructionBlockAccessList) EncodeRLP(wr io.Writer) error {
|
||||||
|
return b.toEncodingObj().EncodeRLP(wr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ rlp.Encoder = &ConstructionBlockAccessList{}
|
||||||
|
|
||||||
|
// toEncodingObj creates an instance of the ConstructionAccountAccess of the type that is
|
||||||
|
// used as input for the encoding.
|
||||||
|
func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess {
|
||||||
|
res := AccountAccess{
|
||||||
|
Address: addr,
|
||||||
|
StorageWrites: make([]encodingSlotWrites, 0),
|
||||||
|
StorageReads: make([][32]byte, 0),
|
||||||
|
BalanceChanges: make([]encodingBalanceChange, 0),
|
||||||
|
NonceChanges: make([]encodingAccountNonce, 0),
|
||||||
|
Code: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert write slots
|
||||||
|
writeSlots := slices.Collect(maps.Keys(a.StorageWrites))
|
||||||
|
slices.SortFunc(writeSlots, common.Hash.Cmp)
|
||||||
|
for _, slot := range writeSlots {
|
||||||
|
var obj encodingSlotWrites
|
||||||
|
obj.Slot = slot
|
||||||
|
|
||||||
|
slotWrites := a.StorageWrites[slot]
|
||||||
|
obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites))
|
||||||
|
|
||||||
|
indices := slices.Collect(maps.Keys(slotWrites))
|
||||||
|
slices.SortFunc(indices, cmp.Compare[uint16])
|
||||||
|
for _, index := range indices {
|
||||||
|
obj.Accesses = append(obj.Accesses, encodingStorageWrite{
|
||||||
|
TxIdx: index,
|
||||||
|
ValueAfter: slotWrites[index],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
res.StorageWrites = append(res.StorageWrites, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert read slots
|
||||||
|
readSlots := slices.Collect(maps.Keys(a.StorageReads))
|
||||||
|
slices.SortFunc(readSlots, common.Hash.Cmp)
|
||||||
|
for _, slot := range readSlots {
|
||||||
|
res.StorageReads = append(res.StorageReads, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert balance changes
|
||||||
|
balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges))
|
||||||
|
slices.SortFunc(balanceIndices, cmp.Compare[uint16])
|
||||||
|
for _, idx := range balanceIndices {
|
||||||
|
res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{
|
||||||
|
TxIdx: idx,
|
||||||
|
Balance: encodeBalance(a.BalanceChanges[idx]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert nonce changes
|
||||||
|
nonceIndices := slices.Collect(maps.Keys(a.NonceChanges))
|
||||||
|
slices.SortFunc(nonceIndices, cmp.Compare[uint16])
|
||||||
|
for _, idx := range nonceIndices {
|
||||||
|
res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{
|
||||||
|
TxIdx: idx,
|
||||||
|
Nonce: a.NonceChanges[idx],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert code change
|
||||||
|
if a.CodeChange != nil {
|
||||||
|
res.Code = []CodeChange{
|
||||||
|
{
|
||||||
|
a.CodeChange.TxIndex,
|
||||||
|
bytes.Clone(a.CodeChange.Code),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// toEncodingObj returns an instance of the access list expressed as the type
|
||||||
|
// which is used as input for the encoding/decoding.
|
||||||
|
func (b *ConstructionBlockAccessList) toEncodingObj() *BlockAccessList {
|
||||||
|
var addresses []common.Address
|
||||||
|
for addr := range b.Accounts {
|
||||||
|
addresses = append(addresses, addr)
|
||||||
|
}
|
||||||
|
slices.SortFunc(addresses, common.Address.Cmp)
|
||||||
|
|
||||||
|
var res BlockAccessList
|
||||||
|
for _, addr := range addresses {
|
||||||
|
res.Accesses = append(res.Accesses, b.Accounts[addr].toEncodingObj(addr))
|
||||||
|
}
|
||||||
|
return &res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BlockAccessList) PrettyPrint() string {
|
||||||
|
var res bytes.Buffer
|
||||||
|
printWithIndent := func(indent int, text string) {
|
||||||
|
fmt.Fprintf(&res, "%s%s\n", strings.Repeat(" ", indent), text)
|
||||||
|
}
|
||||||
|
for _, accountDiff := range e.Accesses {
|
||||||
|
printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address))
|
||||||
|
|
||||||
|
printWithIndent(1, "storage writes:")
|
||||||
|
for _, sWrite := range accountDiff.StorageWrites {
|
||||||
|
printWithIndent(2, fmt.Sprintf("%x:", sWrite.Slot))
|
||||||
|
for _, access := range sWrite.Accesses {
|
||||||
|
printWithIndent(3, fmt.Sprintf("%d: %x", access.TxIdx, access.ValueAfter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printWithIndent(1, "storage reads:")
|
||||||
|
for _, slot := range accountDiff.StorageReads {
|
||||||
|
printWithIndent(2, fmt.Sprintf("%x", slot))
|
||||||
|
}
|
||||||
|
|
||||||
|
printWithIndent(1, "balance changes:")
|
||||||
|
for _, change := range accountDiff.BalanceChanges {
|
||||||
|
balance := new(uint256.Int).SetBytes(change.Balance[:]).String()
|
||||||
|
printWithIndent(2, fmt.Sprintf("%d: %s", change.TxIdx, balance))
|
||||||
|
}
|
||||||
|
|
||||||
|
printWithIndent(1, "nonce changes:")
|
||||||
|
for _, change := range accountDiff.NonceChanges {
|
||||||
|
printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(accountDiff.Code) > 0 {
|
||||||
|
printWithIndent(1, "code:")
|
||||||
|
printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the access list
|
||||||
|
func (e *BlockAccessList) Copy() (res BlockAccessList) {
|
||||||
|
for _, accountAccess := range e.Accesses {
|
||||||
|
res.Accesses = append(res.Accesses, accountAccess.Copy())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
280
core/types/bal/bal_encoding_rlp_generated.go
Normal file
280
core/types/bal/bal_encoding_rlp_generated.go
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
// Code generated by rlpgen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package bal
|
||||||
|
|
||||||
|
import "github.com/ethereum/go-ethereum/rlp"
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error {
|
||||||
|
w := rlp.NewEncoderBuffer(_w)
|
||||||
|
_tmp0 := w.List()
|
||||||
|
_tmp1 := w.List()
|
||||||
|
for _, _tmp2 := range obj.Accesses {
|
||||||
|
_tmp3 := w.List()
|
||||||
|
w.WriteBytes(_tmp2.Address[:])
|
||||||
|
_tmp4 := w.List()
|
||||||
|
for _, _tmp5 := range _tmp2.StorageWrites {
|
||||||
|
_tmp6 := w.List()
|
||||||
|
w.WriteBytes(_tmp5.Slot[:])
|
||||||
|
_tmp7 := w.List()
|
||||||
|
for _, _tmp8 := range _tmp5.Accesses {
|
||||||
|
_tmp9 := w.List()
|
||||||
|
w.WriteUint64(uint64(_tmp8.TxIdx))
|
||||||
|
w.WriteBytes(_tmp8.ValueAfter[:])
|
||||||
|
w.ListEnd(_tmp9)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp7)
|
||||||
|
w.ListEnd(_tmp6)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp4)
|
||||||
|
_tmp10 := w.List()
|
||||||
|
for _, _tmp11 := range _tmp2.StorageReads {
|
||||||
|
w.WriteBytes(_tmp11[:])
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp10)
|
||||||
|
_tmp12 := w.List()
|
||||||
|
for _, _tmp13 := range _tmp2.BalanceChanges {
|
||||||
|
_tmp14 := w.List()
|
||||||
|
w.WriteUint64(uint64(_tmp13.TxIdx))
|
||||||
|
w.WriteBytes(_tmp13.Balance[:])
|
||||||
|
w.ListEnd(_tmp14)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp12)
|
||||||
|
_tmp15 := w.List()
|
||||||
|
for _, _tmp16 := range _tmp2.NonceChanges {
|
||||||
|
_tmp17 := w.List()
|
||||||
|
w.WriteUint64(uint64(_tmp16.TxIdx))
|
||||||
|
w.WriteUint64(_tmp16.Nonce)
|
||||||
|
w.ListEnd(_tmp17)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp15)
|
||||||
|
_tmp18 := w.List()
|
||||||
|
for _, _tmp19 := range _tmp2.Code {
|
||||||
|
_tmp20 := w.List()
|
||||||
|
w.WriteUint64(uint64(_tmp19.TxIndex))
|
||||||
|
w.WriteBytes(_tmp19.Code)
|
||||||
|
w.ListEnd(_tmp20)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp18)
|
||||||
|
w.ListEnd(_tmp3)
|
||||||
|
}
|
||||||
|
w.ListEnd(_tmp1)
|
||||||
|
w.ListEnd(_tmp0)
|
||||||
|
return w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
|
var _tmp0 BlockAccessList
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Accesses:
|
||||||
|
var _tmp1 []AccountAccess
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp2 AccountAccess
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Address:
|
||||||
|
var _tmp3 [20]byte
|
||||||
|
if err := dec.ReadBytes(_tmp3[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.Address = _tmp3
|
||||||
|
// StorageWrites:
|
||||||
|
var _tmp4 []encodingSlotWrites
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp5 encodingSlotWrites
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Slot:
|
||||||
|
var _tmp6 [32]byte
|
||||||
|
if err := dec.ReadBytes(_tmp6[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp5.Slot = _tmp6
|
||||||
|
// Accesses:
|
||||||
|
var _tmp7 []encodingStorageWrite
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp8 encodingStorageWrite
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// TxIdx:
|
||||||
|
_tmp9, err := dec.Uint16()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp8.TxIdx = _tmp9
|
||||||
|
// ValueAfter:
|
||||||
|
var _tmp10 [32]byte
|
||||||
|
if err := dec.ReadBytes(_tmp10[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp8.ValueAfter = _tmp10
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp7 = append(_tmp7, _tmp8)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp5.Accesses = _tmp7
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp4 = append(_tmp4, _tmp5)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.StorageWrites = _tmp4
|
||||||
|
// StorageReads:
|
||||||
|
var _tmp11 [][32]byte
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp12 [32]byte
|
||||||
|
if err := dec.ReadBytes(_tmp12[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp11 = append(_tmp11, _tmp12)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.StorageReads = _tmp11
|
||||||
|
// BalanceChanges:
|
||||||
|
var _tmp13 []encodingBalanceChange
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp14 encodingBalanceChange
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// TxIdx:
|
||||||
|
_tmp15, err := dec.Uint16()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp14.TxIdx = _tmp15
|
||||||
|
// Balance:
|
||||||
|
var _tmp16 [16]byte
|
||||||
|
if err := dec.ReadBytes(_tmp16[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp14.Balance = _tmp16
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp13 = append(_tmp13, _tmp14)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.BalanceChanges = _tmp13
|
||||||
|
// NonceChanges:
|
||||||
|
var _tmp17 []encodingAccountNonce
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp18 encodingAccountNonce
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// TxIdx:
|
||||||
|
_tmp19, err := dec.Uint16()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp18.TxIdx = _tmp19
|
||||||
|
// Nonce:
|
||||||
|
_tmp20, err := dec.Uint64()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp18.Nonce = _tmp20
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp17 = append(_tmp17, _tmp18)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.NonceChanges = _tmp17
|
||||||
|
// Code:
|
||||||
|
var _tmp21 []CodeChange
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dec.MoreDataInList() {
|
||||||
|
var _tmp22 CodeChange
|
||||||
|
{
|
||||||
|
if _, err := dec.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// TxIndex:
|
||||||
|
_tmp23, err := dec.Uint16()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp22.TxIndex = _tmp23
|
||||||
|
// Code:
|
||||||
|
_tmp24, err := dec.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp22.Code = _tmp24
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp21 = append(_tmp21, _tmp22)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp2.Code = _tmp21
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tmp1 = append(_tmp1, _tmp2)
|
||||||
|
}
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_tmp0.Accesses = _tmp1
|
||||||
|
if err := dec.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*obj = _tmp0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
252
core/types/bal/bal_test.go
Normal file
252
core/types/bal/bal_test.go
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
// Copyright 2025 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 bal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"cmp"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
)
|
||||||
|
|
||||||
|
func equalBALs(a *BlockAccessList, b *BlockAccessList) bool {
|
||||||
|
if !reflect.DeepEqual(a, b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
||||||
|
return &ConstructionBlockAccessList{
|
||||||
|
map[common.Address]*ConstructionAccountAccess{
|
||||||
|
common.BytesToAddress([]byte{0xff, 0xff}): {
|
||||||
|
StorageWrites: map[common.Hash]map[uint16]common.Hash{
|
||||||
|
common.BytesToHash([]byte{0x01}): {
|
||||||
|
1: common.BytesToHash([]byte{1, 2, 3, 4}),
|
||||||
|
2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}),
|
||||||
|
},
|
||||||
|
common.BytesToHash([]byte{0x10}): {
|
||||||
|
20: common.BytesToHash([]byte{1, 2, 3, 4}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
StorageReads: map[common.Hash]struct{}{
|
||||||
|
common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7}): {},
|
||||||
|
},
|
||||||
|
BalanceChanges: map[uint16]*uint256.Int{
|
||||||
|
1: uint256.NewInt(100),
|
||||||
|
2: uint256.NewInt(500),
|
||||||
|
},
|
||||||
|
NonceChanges: map[uint16]uint64{
|
||||||
|
1: 2,
|
||||||
|
2: 6,
|
||||||
|
},
|
||||||
|
CodeChange: &CodeChange{
|
||||||
|
TxIndex: 0,
|
||||||
|
Code: common.Hex2Bytes("deadbeef"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
common.BytesToAddress([]byte{0xff, 0xff, 0xff}): {
|
||||||
|
StorageWrites: map[common.Hash]map[uint16]common.Hash{
|
||||||
|
common.BytesToHash([]byte{0x01}): {
|
||||||
|
2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}),
|
||||||
|
3: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
|
||||||
|
},
|
||||||
|
common.BytesToHash([]byte{0x10}): {
|
||||||
|
21: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
StorageReads: map[common.Hash]struct{}{
|
||||||
|
common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}): {},
|
||||||
|
},
|
||||||
|
BalanceChanges: map[uint16]*uint256.Int{
|
||||||
|
2: uint256.NewInt(100),
|
||||||
|
3: uint256.NewInt(500),
|
||||||
|
},
|
||||||
|
NonceChanges: map[uint16]uint64{
|
||||||
|
1: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestBALEncoding tests that a populated access list can be encoded/decoded correctly.
|
||||||
|
func TestBALEncoding(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
bal := makeTestConstructionBAL()
|
||||||
|
err := bal.EncodeRLP(&buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("encoding failed: %v\n", err)
|
||||||
|
}
|
||||||
|
var dec BlockAccessList
|
||||||
|
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 10000000)); err != nil {
|
||||||
|
t.Fatalf("decoding failed: %v\n", err)
|
||||||
|
}
|
||||||
|
if dec.Hash() != bal.toEncodingObj().Hash() {
|
||||||
|
t.Fatalf("encoded block hash doesn't match decoded")
|
||||||
|
}
|
||||||
|
if !equalBALs(bal.toEncodingObj(), &dec) {
|
||||||
|
t.Fatal("decoded BAL doesn't match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTestAccountAccess(sort bool) AccountAccess {
|
||||||
|
var (
|
||||||
|
storageWrites []encodingSlotWrites
|
||||||
|
storageReads [][32]byte
|
||||||
|
balances []encodingBalanceChange
|
||||||
|
nonces []encodingAccountNonce
|
||||||
|
)
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
slot := encodingSlotWrites{
|
||||||
|
Slot: testrand.Hash(),
|
||||||
|
}
|
||||||
|
for j := 0; j < 3; j++ {
|
||||||
|
slot.Accesses = append(slot.Accesses, encodingStorageWrite{
|
||||||
|
TxIdx: uint16(2 * j),
|
||||||
|
ValueAfter: testrand.Hash(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(slot.Accesses, func(a, b encodingStorageWrite) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
storageWrites = append(storageWrites, slot)
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int {
|
||||||
|
return bytes.Compare(a.Slot[:], b.Slot[:])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
storageReads = append(storageReads, testrand.Hash())
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(storageReads, func(a, b [32]byte) int {
|
||||||
|
return bytes.Compare(a[:], b[:])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
balances = append(balances, encodingBalanceChange{
|
||||||
|
TxIdx: uint16(2 * i),
|
||||||
|
Balance: [16]byte(testrand.Bytes(16)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(balances, func(a, b encodingBalanceChange) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
nonces = append(nonces, encodingAccountNonce{
|
||||||
|
TxIdx: uint16(2 * i),
|
||||||
|
Nonce: uint64(i + 100),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(nonces, func(a, b encodingAccountNonce) int {
|
||||||
|
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return AccountAccess{
|
||||||
|
Address: [20]byte(testrand.Bytes(20)),
|
||||||
|
StorageWrites: storageWrites,
|
||||||
|
StorageReads: storageReads,
|
||||||
|
BalanceChanges: balances,
|
||||||
|
NonceChanges: nonces,
|
||||||
|
Code: []CodeChange{
|
||||||
|
{
|
||||||
|
TxIndex: 100,
|
||||||
|
Code: testrand.Bytes(256),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTestBAL(sort bool) BlockAccessList {
|
||||||
|
list := BlockAccessList{}
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
list.Accesses = append(list.Accesses, makeTestAccountAccess(sort))
|
||||||
|
}
|
||||||
|
if sort {
|
||||||
|
slices.SortFunc(list.Accesses, func(a, b AccountAccess) int {
|
||||||
|
return bytes.Compare(a.Address[:], b.Address[:])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBlockAccessListCopy(t *testing.T) {
|
||||||
|
list := makeTestBAL(true)
|
||||||
|
cpy := list.Copy()
|
||||||
|
cpyCpy := cpy.Copy()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(list, cpy) {
|
||||||
|
t.Fatal("block access mismatch")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(cpy, cpyCpy) {
|
||||||
|
t.Fatal("block access mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the mutations on copy won't affect the origin
|
||||||
|
for _, aa := range cpyCpy.Accesses {
|
||||||
|
for i := 0; i < len(aa.StorageReads); i++ {
|
||||||
|
aa.StorageReads[i] = [32]byte(testrand.Bytes(32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(list, cpy) {
|
||||||
|
t.Fatal("block access mismatch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBlockAccessListValidation(t *testing.T) {
|
||||||
|
// Validate the block access list after RLP decoding
|
||||||
|
enc := makeTestBAL(true)
|
||||||
|
if err := enc.Validate(); err != nil {
|
||||||
|
t.Fatalf("Unexpected validation error: %v", err)
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := enc.EncodeRLP(&buf); err != nil {
|
||||||
|
t.Fatalf("Unexpected encoding error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dec BlockAccessList
|
||||||
|
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 0)); err != nil {
|
||||||
|
t.Fatalf("Unexpected RLP-decode error: %v", err)
|
||||||
|
}
|
||||||
|
if err := dec.Validate(); err != nil {
|
||||||
|
t.Fatalf("Unexpected validation error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the derived block access list
|
||||||
|
cBAL := makeTestConstructionBAL()
|
||||||
|
listB := cBAL.toEncodingObj()
|
||||||
|
if err := listB.Validate(); err != nil {
|
||||||
|
t.Fatalf("Unexpected validation error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -32,6 +31,18 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BlobSidecarVersion0 includes a single proof for verifying the entire blob
|
||||||
|
// against its commitment. Used when the full blob is available and needs to
|
||||||
|
// be checked as a whole.
|
||||||
|
BlobSidecarVersion0 = byte(0)
|
||||||
|
|
||||||
|
// BlobSidecarVersion1 includes multiple cell proofs for verifying specific
|
||||||
|
// blob elements (cells). Used in scenarios like data availability sampling,
|
||||||
|
// where only portions of the blob are verified individually.
|
||||||
|
BlobSidecarVersion1 = byte(1)
|
||||||
|
)
|
||||||
|
|
||||||
// BlobTx represents an EIP-4844 transaction.
|
// BlobTx represents an EIP-4844 transaction.
|
||||||
type BlobTx struct {
|
type BlobTx struct {
|
||||||
ChainID *uint256.Int
|
ChainID *uint256.Int
|
||||||
|
|
@ -64,6 +75,16 @@ type BlobTxSidecar struct {
|
||||||
Proofs []kzg4844.Proof // Proofs needed by the blob pool
|
Proofs []kzg4844.Proof // Proofs needed by the blob pool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBlobTxSidecar initialises the BlobTxSidecar object with the provided parameters.
|
||||||
|
func NewBlobTxSidecar(version byte, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *BlobTxSidecar {
|
||||||
|
return &BlobTxSidecar{
|
||||||
|
Version: version,
|
||||||
|
Blobs: blobs,
|
||||||
|
Commitments: commitments,
|
||||||
|
Proofs: proofs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BlobHashes computes the blob hashes of the given blobs.
|
// BlobHashes computes the blob hashes of the given blobs.
|
||||||
func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
|
func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
|
||||||
hasher := sha256.New()
|
hasher := sha256.New()
|
||||||
|
|
@ -75,17 +96,39 @@ func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CellProofsAt returns the cell proofs for blob with index idx.
|
// CellProofsAt returns the cell proofs for blob with index idx.
|
||||||
func (sc *BlobTxSidecar) CellProofsAt(idx int) []kzg4844.Proof {
|
// This method is only valid for sidecars with version 1.
|
||||||
var cellProofs []kzg4844.Proof
|
func (sc *BlobTxSidecar) CellProofsAt(idx int) ([]kzg4844.Proof, error) {
|
||||||
for i := range kzg4844.CellProofsPerBlob {
|
if sc.Version != BlobSidecarVersion1 {
|
||||||
index := idx*kzg4844.CellProofsPerBlob + i
|
return nil, fmt.Errorf("cell proof unsupported, version: %d", sc.Version)
|
||||||
if index > len(sc.Proofs) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
proof := sc.Proofs[index]
|
|
||||||
cellProofs = append(cellProofs, proof)
|
|
||||||
}
|
}
|
||||||
return cellProofs
|
if idx < 0 || idx >= len(sc.Blobs) {
|
||||||
|
return nil, fmt.Errorf("cell proof out of bounds, index: %d, blobs: %d", idx, len(sc.Blobs))
|
||||||
|
}
|
||||||
|
index := idx * kzg4844.CellProofsPerBlob
|
||||||
|
if len(sc.Proofs) < index+kzg4844.CellProofsPerBlob {
|
||||||
|
return nil, fmt.Errorf("cell proof is corrupted, index: %d, proofs: %d", idx, len(sc.Proofs))
|
||||||
|
}
|
||||||
|
return sc.Proofs[index : index+kzg4844.CellProofsPerBlob], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToV1 converts the BlobSidecar to version 1, attaching the cell proofs.
|
||||||
|
func (sc *BlobTxSidecar) ToV1() error {
|
||||||
|
if sc.Version == BlobSidecarVersion1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if sc.Version == BlobSidecarVersion0 {
|
||||||
|
proofs := make([]kzg4844.Proof, 0, len(sc.Blobs)*kzg4844.CellProofsPerBlob)
|
||||||
|
for _, blob := range sc.Blobs {
|
||||||
|
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
proofs = append(proofs, cellProofs...)
|
||||||
|
}
|
||||||
|
sc.Version = BlobSidecarVersion1
|
||||||
|
sc.Proofs = proofs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodedSize computes the RLP size of the sidecar elements. This does NOT return the
|
// encodedSize computes the RLP size of the sidecar elements. This does NOT return the
|
||||||
|
|
@ -120,6 +163,19 @@ func (sc *BlobTxSidecar) ValidateBlobCommitmentHashes(hashes []common.Hash) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep-copied BlobTxSidecar object.
|
||||||
|
func (sc *BlobTxSidecar) Copy() *BlobTxSidecar {
|
||||||
|
return &BlobTxSidecar{
|
||||||
|
Version: sc.Version,
|
||||||
|
|
||||||
|
// The element of these slice is fix-size byte array,
|
||||||
|
// therefore slices.Clone will actually deep copy by value.
|
||||||
|
Blobs: slices.Clone(sc.Blobs),
|
||||||
|
Commitments: slices.Clone(sc.Commitments),
|
||||||
|
Proofs: slices.Clone(sc.Proofs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// blobTxWithBlobs represents blob tx with its corresponding sidecar.
|
// blobTxWithBlobs represents blob tx with its corresponding sidecar.
|
||||||
// This is an interface because sidecars are versioned.
|
// This is an interface because sidecars are versioned.
|
||||||
type blobTxWithBlobs interface {
|
type blobTxWithBlobs interface {
|
||||||
|
|
@ -147,7 +203,7 @@ func (btx *blobTxWithBlobsV0) tx() *BlobTx {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV0) assign(sc *BlobTxSidecar) error {
|
func (btx *blobTxWithBlobsV0) assign(sc *BlobTxSidecar) error {
|
||||||
sc.Version = 0
|
sc.Version = BlobSidecarVersion0
|
||||||
sc.Blobs = btx.Blobs
|
sc.Blobs = btx.Blobs
|
||||||
sc.Commitments = btx.Commitments
|
sc.Commitments = btx.Commitments
|
||||||
sc.Proofs = btx.Proofs
|
sc.Proofs = btx.Proofs
|
||||||
|
|
@ -159,10 +215,10 @@ func (btx *blobTxWithBlobsV1) tx() *BlobTx {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV1) assign(sc *BlobTxSidecar) error {
|
func (btx *blobTxWithBlobsV1) assign(sc *BlobTxSidecar) error {
|
||||||
if btx.Version != 1 {
|
if btx.Version != BlobSidecarVersion1 {
|
||||||
return fmt.Errorf("unsupported blob tx version %d", btx.Version)
|
return fmt.Errorf("unsupported blob tx version %d", btx.Version)
|
||||||
}
|
}
|
||||||
sc.Version = 1
|
sc.Version = BlobSidecarVersion1
|
||||||
sc.Blobs = btx.Blobs
|
sc.Blobs = btx.Blobs
|
||||||
sc.Commitments = btx.Commitments
|
sc.Commitments = btx.Commitments
|
||||||
sc.Proofs = btx.Proofs
|
sc.Proofs = btx.Proofs
|
||||||
|
|
@ -216,11 +272,7 @@ func (tx *BlobTx) copy() TxData {
|
||||||
cpy.S.Set(tx.S)
|
cpy.S.Set(tx.S)
|
||||||
}
|
}
|
||||||
if tx.Sidecar != nil {
|
if tx.Sidecar != nil {
|
||||||
cpy.Sidecar = &BlobTxSidecar{
|
cpy.Sidecar = tx.Sidecar.Copy()
|
||||||
Blobs: slices.Clone(tx.Sidecar.Blobs),
|
|
||||||
Commitments: slices.Clone(tx.Sidecar.Commitments),
|
|
||||||
Proofs: slices.Clone(tx.Sidecar.Proofs),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cpy
|
return cpy
|
||||||
}
|
}
|
||||||
|
|
@ -278,7 +330,7 @@ func (tx *BlobTx) encode(b *bytes.Buffer) error {
|
||||||
case tx.Sidecar == nil:
|
case tx.Sidecar == nil:
|
||||||
return rlp.Encode(b, tx)
|
return rlp.Encode(b, tx)
|
||||||
|
|
||||||
case tx.Sidecar.Version == 0:
|
case tx.Sidecar.Version == BlobSidecarVersion0:
|
||||||
return rlp.Encode(b, &blobTxWithBlobsV0{
|
return rlp.Encode(b, &blobTxWithBlobsV0{
|
||||||
BlobTx: tx,
|
BlobTx: tx,
|
||||||
Blobs: tx.Sidecar.Blobs,
|
Blobs: tx.Sidecar.Blobs,
|
||||||
|
|
@ -286,7 +338,7 @@ func (tx *BlobTx) encode(b *bytes.Buffer) error {
|
||||||
Proofs: tx.Sidecar.Proofs,
|
Proofs: tx.Sidecar.Proofs,
|
||||||
})
|
})
|
||||||
|
|
||||||
case tx.Sidecar.Version == 1:
|
case tx.Sidecar.Version == BlobSidecarVersion1:
|
||||||
return rlp.Encode(b, &blobTxWithBlobsV1{
|
return rlp.Encode(b, &blobTxWithBlobsV1{
|
||||||
BlobTx: tx,
|
BlobTx: tx,
|
||||||
Version: tx.Sidecar.Version,
|
Version: tx.Sidecar.Version,
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,7 @@ func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
|
func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
|
||||||
sidecar := &BlobTxSidecar{
|
sidecar := NewBlobTxSidecar(BlobSidecarVersion0, []kzg4844.Blob{*emptyBlob}, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof})
|
||||||
Blobs: []kzg4844.Blob{*emptyBlob},
|
|
||||||
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
|
||||||
Proofs: []kzg4844.Proof{emptyBlobProof},
|
|
||||||
}
|
|
||||||
blobtx := &BlobTx{
|
blobtx := &BlobTx{
|
||||||
ChainID: uint256.NewInt(1),
|
ChainID: uint256.NewInt(1),
|
||||||
Nonce: 5,
|
Nonce: 5,
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ type authorizationMarshaling struct {
|
||||||
|
|
||||||
// SignSetCode creates a signed the SetCode authorization.
|
// SignSetCode creates a signed the SetCode authorization.
|
||||||
func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAuthorization, error) {
|
func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAuthorization, error) {
|
||||||
sighash := auth.sigHash()
|
sighash := auth.SigHash()
|
||||||
sig, err := crypto.Sign(sighash[:], prv)
|
sig, err := crypto.Sign(sighash[:], prv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SetCodeAuthorization{}, err
|
return SetCodeAuthorization{}, err
|
||||||
|
|
@ -105,7 +105,8 @@ func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAutho
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SetCodeAuthorization) sigHash() common.Hash {
|
// SigHash returns the hash of SetCodeAuthorization for signing.
|
||||||
|
func (a *SetCodeAuthorization) SigHash() common.Hash {
|
||||||
return prefixedRlpHash(0x05, []any{
|
return prefixedRlpHash(0x05, []any{
|
||||||
a.ChainID,
|
a.ChainID,
|
||||||
a.Address,
|
a.Address,
|
||||||
|
|
@ -115,7 +116,7 @@ func (a *SetCodeAuthorization) sigHash() common.Hash {
|
||||||
|
|
||||||
// Authority recovers the the authorizing account of an authorization.
|
// Authority recovers the the authorizing account of an authorization.
|
||||||
func (a *SetCodeAuthorization) Authority() (common.Address, error) {
|
func (a *SetCodeAuthorization) Authority() (common.Address, error) {
|
||||||
sighash := a.sigHash()
|
sighash := a.SigHash()
|
||||||
if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) {
|
if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) {
|
||||||
return common.Address{}, ErrInvalidSig
|
return common.Address{}, ErrInvalidSig
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,16 @@ const (
|
||||||
set7BitsMask = uint16(0b111_1111)
|
set7BitsMask = uint16(0b111_1111)
|
||||||
)
|
)
|
||||||
|
|
||||||
// bitvec is a bit vector which maps bytes in a program.
|
// BitVec is a bit vector which maps bytes in a program.
|
||||||
// An unset bit means the byte is an opcode, a set bit means
|
// An unset bit means the byte is an opcode, a set bit means
|
||||||
// it's data (i.e. argument of PUSHxx).
|
// it's data (i.e. argument of PUSHxx).
|
||||||
type bitvec []byte
|
type BitVec []byte
|
||||||
|
|
||||||
func (bits bitvec) set1(pos uint64) {
|
func (bits BitVec) set1(pos uint64) {
|
||||||
bits[pos/8] |= 1 << (pos % 8)
|
bits[pos/8] |= 1 << (pos % 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bits bitvec) setN(flag uint16, pos uint64) {
|
func (bits BitVec) setN(flag uint16, pos uint64) {
|
||||||
a := flag << (pos % 8)
|
a := flag << (pos % 8)
|
||||||
bits[pos/8] |= byte(a)
|
bits[pos/8] |= byte(a)
|
||||||
if b := byte(a >> 8); b != 0 {
|
if b := byte(a >> 8); b != 0 {
|
||||||
|
|
@ -42,13 +42,13 @@ func (bits bitvec) setN(flag uint16, pos uint64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bits bitvec) set8(pos uint64) {
|
func (bits BitVec) set8(pos uint64) {
|
||||||
a := byte(0xFF << (pos % 8))
|
a := byte(0xFF << (pos % 8))
|
||||||
bits[pos/8] |= a
|
bits[pos/8] |= a
|
||||||
bits[pos/8+1] = ^a
|
bits[pos/8+1] = ^a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bits bitvec) set16(pos uint64) {
|
func (bits BitVec) set16(pos uint64) {
|
||||||
a := byte(0xFF << (pos % 8))
|
a := byte(0xFF << (pos % 8))
|
||||||
bits[pos/8] |= a
|
bits[pos/8] |= a
|
||||||
bits[pos/8+1] = 0xFF
|
bits[pos/8+1] = 0xFF
|
||||||
|
|
@ -56,23 +56,23 @@ func (bits bitvec) set16(pos uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeSegment checks if the position is in a code segment.
|
// codeSegment checks if the position is in a code segment.
|
||||||
func (bits *bitvec) codeSegment(pos uint64) bool {
|
func (bits *BitVec) codeSegment(pos uint64) bool {
|
||||||
return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0
|
return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeBitmap collects data locations in code.
|
// codeBitmap collects data locations in code.
|
||||||
func codeBitmap(code []byte) bitvec {
|
func codeBitmap(code []byte) BitVec {
|
||||||
// The bitmap is 4 bytes longer than necessary, in case the code
|
// The bitmap is 4 bytes longer than necessary, in case the code
|
||||||
// ends with a PUSH32, the algorithm will set bits on the
|
// ends with a PUSH32, the algorithm will set bits on the
|
||||||
// bitvector outside the bounds of the actual code.
|
// bitvector outside the bounds of the actual code.
|
||||||
bits := make(bitvec, len(code)/8+1+4)
|
bits := make(BitVec, len(code)/8+1+4)
|
||||||
return codeBitmapInternal(code, bits)
|
return codeBitmapInternal(code, bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeBitmapInternal is the internal implementation of codeBitmap.
|
// codeBitmapInternal is the internal implementation of codeBitmap.
|
||||||
// It exists for the purpose of being able to run benchmark tests
|
// It exists for the purpose of being able to run benchmark tests
|
||||||
// without dynamic allocations affecting the results.
|
// without dynamic allocations affecting the results.
|
||||||
func codeBitmapInternal(code, bits bitvec) bitvec {
|
func codeBitmapInternal(code, bits BitVec) BitVec {
|
||||||
for pc := uint64(0); pc < uint64(len(code)); {
|
for pc := uint64(0); pc < uint64(len(code)); {
|
||||||
op := OpCode(code[pc])
|
op := OpCode(code[pc])
|
||||||
pc++
|
pc++
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
|
||||||
for i := range code {
|
for i := range code {
|
||||||
code[i] = byte(op)
|
code[i] = byte(op)
|
||||||
}
|
}
|
||||||
bits := make(bitvec, len(code)/8+1+4)
|
bits := make(BitVec, len(code)/8+1+4)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
clear(bits)
|
clear(bits)
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ type Contract struct {
|
||||||
caller common.Address
|
caller common.Address
|
||||||
address common.Address
|
address common.Address
|
||||||
|
|
||||||
jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
|
jumpDests JumpDestCache // Aggregated result of JUMPDEST analysis.
|
||||||
analysis bitvec // Locally cached result of JUMPDEST analysis
|
analysis BitVec // Locally cached result of JUMPDEST analysis
|
||||||
|
|
||||||
Code []byte
|
Code []byte
|
||||||
CodeHash common.Hash
|
CodeHash common.Hash
|
||||||
|
|
@ -47,15 +47,15 @@ type Contract struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContract returns a new contract environment for the execution of EVM.
|
// NewContract returns a new contract environment for the execution of EVM.
|
||||||
func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests map[common.Hash]bitvec) *Contract {
|
func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests JumpDestCache) *Contract {
|
||||||
// Initialize the jump analysis map if it's nil, mostly for tests
|
// Initialize the jump analysis cache if it's nil, mostly for tests
|
||||||
if jumpDests == nil {
|
if jumpDests == nil {
|
||||||
jumpDests = make(map[common.Hash]bitvec)
|
jumpDests = newMapJumpDests()
|
||||||
}
|
}
|
||||||
return &Contract{
|
return &Contract{
|
||||||
caller: caller,
|
caller: caller,
|
||||||
address: address,
|
address: address,
|
||||||
jumpdests: jumpDests,
|
jumpDests: jumpDests,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
|
|
@ -87,12 +87,12 @@ func (c *Contract) isCode(udest uint64) bool {
|
||||||
// contracts ( not temporary initcode), we store the analysis in a map
|
// contracts ( not temporary initcode), we store the analysis in a map
|
||||||
if c.CodeHash != (common.Hash{}) {
|
if c.CodeHash != (common.Hash{}) {
|
||||||
// Does parent context have the analysis?
|
// Does parent context have the analysis?
|
||||||
analysis, exist := c.jumpdests[c.CodeHash]
|
analysis, exist := c.jumpDests.Load(c.CodeHash)
|
||||||
if !exist {
|
if !exist {
|
||||||
// Do the analysis and save in parent context
|
// Do the analysis and save in parent context
|
||||||
// We do not need to store it in c.analysis
|
// We do not need to store it in c.analysis
|
||||||
analysis = codeBitmap(c.Code)
|
analysis = codeBitmap(c.Code)
|
||||||
c.jumpdests[c.CodeHash] = analysis
|
c.jumpDests.Store(c.CodeHash, analysis)
|
||||||
}
|
}
|
||||||
// Also stash it in current contract for faster access
|
// Also stash it in current contract for faster access
|
||||||
c.analysis = analysis
|
c.analysis = analysis
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,9 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
||||||
gas.Mul(gas, adjExpLen)
|
gas.Mul(gas, adjExpLen)
|
||||||
}
|
}
|
||||||
// 2. Different divisor (`GQUADDIVISOR`) (3)
|
// 2. Different divisor (`GQUADDIVISOR`) (3)
|
||||||
gas.Div(gas, big3)
|
if !c.eip7883 {
|
||||||
|
gas.Div(gas, big3)
|
||||||
|
}
|
||||||
if gas.BitLen() > 64 {
|
if gas.BitLen() > 64 {
|
||||||
return math.MaxUint64
|
return math.MaxUint64
|
||||||
}
|
}
|
||||||
|
|
@ -513,7 +515,7 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
// enforce size cap for inputs
|
// enforce size cap for inputs
|
||||||
if c.eip7823 && max(baseLen, expLen, modLen) > 1024 {
|
if c.eip7823 && max(baseLen, expLen, modLen) > 1024 {
|
||||||
return nil, fmt.Errorf("one or more of base/exponent/modulus length exceeded 1024 bytes")
|
return nil, errors.New("one or more of base/exponent/modulus length exceeded 1024 bytes")
|
||||||
}
|
}
|
||||||
// Retrieve the operands and execute the exponentiation
|
// Retrieve the operands and execute the exponentiation
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -122,9 +122,8 @@ type EVM struct {
|
||||||
// precompiles holds the precompiled contracts for the current epoch
|
// precompiles holds the precompiled contracts for the current epoch
|
||||||
precompiles map[common.Address]PrecompiledContract
|
precompiles map[common.Address]PrecompiledContract
|
||||||
|
|
||||||
// jumpDests is the aggregated result of JUMPDEST analysis made through
|
// jumpDests stores results of JUMPDEST analysis.
|
||||||
// the life cycle of EVM.
|
jumpDests JumpDestCache
|
||||||
jumpDests map[common.Hash]bitvec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVM constructs an EVM instance with the supplied block context, state
|
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||||
|
|
@ -138,7 +137,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
||||||
Config: config,
|
Config: config,
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
||||||
jumpDests: make(map[common.Hash]bitvec),
|
jumpDests: newMapJumpDests(),
|
||||||
}
|
}
|
||||||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||||
evm.interpreter = NewEVMInterpreter(evm)
|
evm.interpreter = NewEVMInterpreter(evm)
|
||||||
|
|
@ -152,6 +151,11 @@ func (evm *EVM) SetPrecompiles(precompiles PrecompiledContracts) {
|
||||||
evm.precompiles = precompiles
|
evm.precompiles = precompiles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetJumpDestCache configures the analysis cache.
|
||||||
|
func (evm *EVM) SetJumpDestCache(jumpDests JumpDestCache) {
|
||||||
|
evm.jumpDests = jumpDests
|
||||||
|
}
|
||||||
|
|
||||||
// SetTxContext resets the EVM with a new transaction context.
|
// SetTxContext resets the EVM with a new transaction context.
|
||||||
// This is not threadsafe and should only be done very cautiously.
|
// This is not threadsafe and should only be done very cautiously.
|
||||||
func (evm *EVM) SetTxContext(txCtx TxContext) {
|
func (evm *EVM) SetTxContext(txCtx TxContext) {
|
||||||
|
|
|
||||||
47
core/vm/jumpdests.go
Normal file
47
core/vm/jumpdests.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package vm
|
||||||
|
|
||||||
|
import "github.com/ethereum/go-ethereum/common"
|
||||||
|
|
||||||
|
// JumpDestCache represents the cache of jumpdest analysis results.
|
||||||
|
type JumpDestCache interface {
|
||||||
|
// Load retrieves the cached jumpdest analysis for the given code hash.
|
||||||
|
// Returns the BitVec and true if found, or nil and false if not cached.
|
||||||
|
Load(codeHash common.Hash) (BitVec, bool)
|
||||||
|
|
||||||
|
// Store saves the jumpdest analysis for the given code hash.
|
||||||
|
Store(codeHash common.Hash, vec BitVec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapJumpDests is the default implementation of JumpDests using a map.
|
||||||
|
// This implementation is not thread-safe and is meant to be used per EVM instance.
|
||||||
|
type mapJumpDests map[common.Hash]BitVec
|
||||||
|
|
||||||
|
// newMapJumpDests creates a new map-based JumpDests implementation.
|
||||||
|
func newMapJumpDests() JumpDestCache {
|
||||||
|
return make(mapJumpDests)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j mapJumpDests) Load(codeHash common.Hash) (BitVec, bool) {
|
||||||
|
vec, ok := j[codeHash]
|
||||||
|
return vec, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j mapJumpDests) Store(codeHash common.Hash, vec BitVec) {
|
||||||
|
j[codeHash] = vec
|
||||||
|
}
|
||||||
26
core/vm/testdata/precompiles/modexp_eip7883.json
vendored
26
core/vm/testdata/precompiles/modexp_eip7883.json
vendored
|
|
@ -17,91 +17,91 @@
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||||
"Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
|
"Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
|
||||||
"Name": "nagydani-1-pow0x10001",
|
"Name": "nagydani-1-pow0x10001",
|
||||||
"Gas": 682,
|
"Gas": 2048,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||||
"Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
|
"Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
|
||||||
"Name": "nagydani-2-square",
|
"Name": "nagydani-2-square",
|
||||||
"Gas": 500,
|
"Gas": 512,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||||
"Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
|
"Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
|
||||||
"Name": "nagydani-2-qube",
|
"Name": "nagydani-2-qube",
|
||||||
"Gas": 500,
|
"Gas": 512,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||||
"Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
|
"Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
|
||||||
"Name": "nagydani-2-pow0x10001",
|
"Name": "nagydani-2-pow0x10001",
|
||||||
"Gas": 2730,
|
"Gas": 8192,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||||
"Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
|
"Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
|
||||||
"Name": "nagydani-3-square",
|
"Name": "nagydani-3-square",
|
||||||
"Gas": 682,
|
"Gas": 2048,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||||
"Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
|
"Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
|
||||||
"Name": "nagydani-3-qube",
|
"Name": "nagydani-3-qube",
|
||||||
"Gas": 682,
|
"Gas": 2048,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||||
"Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
|
"Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
|
||||||
"Name": "nagydani-3-pow0x10001",
|
"Name": "nagydani-3-pow0x10001",
|
||||||
"Gas": 10922,
|
"Gas": 32768,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||||
"Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
|
"Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
|
||||||
"Name": "nagydani-4-square",
|
"Name": "nagydani-4-square",
|
||||||
"Gas": 2730,
|
"Gas": 8192,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||||
"Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
|
"Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
|
||||||
"Name": "nagydani-4-qube",
|
"Name": "nagydani-4-qube",
|
||||||
"Gas": 2730,
|
"Gas": 8192,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||||
"Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
|
"Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
|
||||||
"Name": "nagydani-4-pow0x10001",
|
"Name": "nagydani-4-pow0x10001",
|
||||||
"Gas": 43690,
|
"Gas": 131072,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||||
"Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
|
"Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
|
||||||
"Name": "nagydani-5-square",
|
"Name": "nagydani-5-square",
|
||||||
"Gas": 10922,
|
"Gas": 32768,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||||
"Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
|
"Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
|
||||||
"Name": "nagydani-5-qube",
|
"Name": "nagydani-5-qube",
|
||||||
"Gas": 10922,
|
"Gas": 32768,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||||
"Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
|
"Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
|
||||||
"Name": "nagydani-5-pow0x10001",
|
"Name": "nagydani-5-pow0x10001",
|
||||||
"Gas": 174762,
|
"Gas": 524288,
|
||||||
"NoBenchmark": false
|
"NoBenchmark": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -236,9 +236,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
VmConfig: vm.Config{
|
VmConfig: vm.Config{
|
||||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||||
},
|
},
|
||||||
|
// Enables file journaling for the trie database. The journal files will be stored
|
||||||
|
// within the data directory. The corresponding paths will be either:
|
||||||
|
// - DATADIR/triedb/merkle.journal
|
||||||
|
// - DATADIR/triedb/verkle.journal
|
||||||
|
TrieJournalDirectory: stack.ResolvePath("triedb"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.VMTrace != "" {
|
if config.VMTrace != "" {
|
||||||
traceConfig := json.RawMessage("{}")
|
traceConfig := json.RawMessage("{}")
|
||||||
if config.VMTraceJsonConfig != "" {
|
if config.VMTraceJsonConfig != "" {
|
||||||
|
|
|
||||||
|
|
@ -527,10 +527,10 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
if len(hashes) > 128 {
|
if len(hashes) > 128 {
|
||||||
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes)))
|
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
available := api.eth.BlobTxPool().AvailableBlobs(hashes)
|
available := api.eth.BlobTxPool().AvailableBlobs(hashes)
|
||||||
getBlobsRequestedCounter.Inc(int64(len(hashes)))
|
getBlobsRequestedCounter.Inc(int64(len(hashes)))
|
||||||
getBlobsAvailableCounter.Inc(int64(available))
|
getBlobsAvailableCounter.Inc(int64(available))
|
||||||
|
|
||||||
// Optimization: check first if all blobs are available, if not, return empty response
|
// Optimization: check first if all blobs are available, if not, return empty response
|
||||||
if available != len(hashes) {
|
if available != len(hashes) {
|
||||||
getBlobsV2RequestMiss.Inc(1)
|
getBlobsV2RequestMiss.Inc(1)
|
||||||
|
|
@ -557,14 +557,17 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
// not found, return empty response
|
// not found, return empty response
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if sidecar.Version != 1 {
|
if sidecar.Version != types.BlobSidecarVersion1 {
|
||||||
log.Info("GetBlobs queried V0 transaction: index %v, blobhashes %v", index, sidecar.BlobHashes())
|
log.Info("GetBlobs queried V0 transaction: index %v, blobhashes %v", index, sidecar.BlobHashes())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
blobHashes := sidecar.BlobHashes()
|
blobHashes := sidecar.BlobHashes()
|
||||||
for bIdx, hash := range blobHashes {
|
for bIdx, hash := range blobHashes {
|
||||||
if idxes, ok := index[hash]; ok {
|
if idxes, ok := index[hash]; ok {
|
||||||
proofs := sidecar.CellProofsAt(bIdx)
|
proofs, err := sidecar.CellProofsAt(bIdx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, engine.InvalidParams.With(err)
|
||||||
|
}
|
||||||
var cellProofs []hexutil.Bytes
|
var cellProofs []hexutil.Bytes
|
||||||
for _, proof := range proofs {
|
for _, proof := range proofs {
|
||||||
cellProofs = append(cellProofs, proof[:])
|
cellProofs = append(cellProofs, proof[:])
|
||||||
|
|
|
||||||
|
|
@ -1497,7 +1497,7 @@ func checkEqualBody(a *types.Body, b *engine.ExecutionPayloadBody) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(a.Withdrawals, b.Withdrawals) {
|
if !reflect.DeepEqual(a.Withdrawals, b.Withdrawals) {
|
||||||
return fmt.Errorf("withdrawals mismatch")
|
return errors.New("withdrawals mismatch")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1511,13 +1511,8 @@ func TestBlockToPayloadWithBlobs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
txs = append(txs, types.NewTx(&inner))
|
txs = append(txs, types.NewTx(&inner))
|
||||||
sidecars := []*types.BlobTxSidecar{
|
sidecar := types.NewBlobTxSidecar(types.BlobSidecarVersion0, make([]kzg4844.Blob, 1), make([]kzg4844.Commitment, 1), make([]kzg4844.Proof, 1))
|
||||||
{
|
sidecars := []*types.BlobTxSidecar{sidecar}
|
||||||
Blobs: make([]kzg4844.Blob, 1),
|
|
||||||
Commitments: make([]kzg4844.Commitment, 1),
|
|
||||||
Proofs: make([]kzg4844.Proof, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
block := types.NewBlock(&header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
|
block := types.NewBlock(&header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
|
||||||
envelope := engine.BlockToExecutableData(block, nil, sidecars, nil)
|
envelope := engine.BlockToExecutableData(block, nil, sidecars, nil)
|
||||||
|
|
|
||||||
|
|
@ -1,103 +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 catalyst
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/node"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FullSyncTester is an auxiliary service that allows Geth to perform full sync
|
|
||||||
// alone without consensus-layer attached. Users must specify a valid block hash
|
|
||||||
// as the sync target.
|
|
||||||
//
|
|
||||||
// This tester can be applied to different networks, no matter it's pre-merge or
|
|
||||||
// post-merge, but only for full-sync.
|
|
||||||
type FullSyncTester struct {
|
|
||||||
stack *node.Node
|
|
||||||
backend *eth.Ethereum
|
|
||||||
target common.Hash
|
|
||||||
closed chan struct{}
|
|
||||||
wg sync.WaitGroup
|
|
||||||
exitWhenSynced bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterFullSyncTester registers the full-sync tester service into the node
|
|
||||||
// stack for launching and stopping the service controlled by node.
|
|
||||||
func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash, exitWhenSynced bool) (*FullSyncTester, error) {
|
|
||||||
cl := &FullSyncTester{
|
|
||||||
stack: stack,
|
|
||||||
backend: backend,
|
|
||||||
target: target,
|
|
||||||
closed: make(chan struct{}),
|
|
||||||
exitWhenSynced: exitWhenSynced,
|
|
||||||
}
|
|
||||||
stack.RegisterLifecycle(cl)
|
|
||||||
return cl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start launches the beacon sync with provided sync target.
|
|
||||||
func (tester *FullSyncTester) Start() error {
|
|
||||||
tester.wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer tester.wg.Done()
|
|
||||||
|
|
||||||
// Trigger beacon sync with the provided block hash as trusted
|
|
||||||
// chain head.
|
|
||||||
err := tester.backend.Downloader().BeaconDevSync(ethconfig.FullSync, tester.target, tester.closed)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Failed to trigger beacon sync", "err", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Second * 5)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
// Stop in case the target block is already stored locally.
|
|
||||||
if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil {
|
|
||||||
log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash())
|
|
||||||
|
|
||||||
if tester.exitWhenSynced {
|
|
||||||
go tester.stack.Close() // async since we need to close ourselves
|
|
||||||
log.Info("Terminating the node")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-tester.closed:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop stops the full-sync tester to stop all background activities.
|
|
||||||
// This function can only be called for one time.
|
|
||||||
func (tester *FullSyncTester) Stop() error {
|
|
||||||
close(tester.closed)
|
|
||||||
tester.wg.Wait()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -228,8 +228,8 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData,
|
||||||
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun")
|
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun")
|
||||||
case executionRequests == nil:
|
case executionRequests == nil:
|
||||||
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague")
|
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague")
|
||||||
case !api.checkFork(params.Timestamp, forks.Prague):
|
case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka):
|
||||||
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads")
|
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
|
||||||
}
|
}
|
||||||
requests := convertRequests(executionRequests)
|
requests := convertRequests(executionRequests)
|
||||||
if err := validateRequests(requests); err != nil {
|
if err := validateRequests(requests); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package downloader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -34,28 +33,14 @@ import (
|
||||||
// Note, this must not be used in live code. If the forkchcoice endpoint where
|
// Note, this must not be used in live code. If the forkchcoice endpoint where
|
||||||
// to use this instead of giving us the payload first, then essentially nobody
|
// to use this instead of giving us the payload first, then essentially nobody
|
||||||
// in the network would have the block yet that we'd attempt to retrieve.
|
// in the network would have the block yet that we'd attempt to retrieve.
|
||||||
func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan struct{}) error {
|
func (d *Downloader) BeaconDevSync(mode SyncMode, header *types.Header) error {
|
||||||
// Be very loud that this code should not be used in a live node
|
// Be very loud that this code should not be used in a live node
|
||||||
log.Warn("----------------------------------")
|
log.Warn("----------------------------------")
|
||||||
log.Warn("Beacon syncing with hash as target", "hash", hash)
|
log.Warn("Beacon syncing with hash as target", "number", header.Number, "hash", header.Hash())
|
||||||
log.Warn("This is unhealthy for a live node!")
|
log.Warn("This is unhealthy for a live node!")
|
||||||
|
log.Warn("This is incompatible with the consensus layer!")
|
||||||
log.Warn("----------------------------------")
|
log.Warn("----------------------------------")
|
||||||
|
return d.BeaconSync(mode, header, header)
|
||||||
log.Info("Waiting for peers to retrieve sync target")
|
|
||||||
for {
|
|
||||||
// If the node is going down, unblock
|
|
||||||
select {
|
|
||||||
case <-stop:
|
|
||||||
return errors.New("stop requested")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
header, err := d.GetHeader(hash)
|
|
||||||
if err != nil {
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return d.BeaconSync(mode, header, header)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeader tries to retrieve the header with a given hash from a random peer.
|
// GetHeader tries to retrieve the header with a given hash from a random peer.
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,9 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
|
||||||
check := (start + end) / 2
|
check := (start + end) / 2
|
||||||
|
|
||||||
h := d.skeleton.Header(check)
|
h := d.skeleton.Header(check)
|
||||||
|
if h == nil {
|
||||||
|
return 0, fmt.Errorf("filled skeleton header is missing: %d", check)
|
||||||
|
}
|
||||||
n := h.Number.Uint64()
|
n := h.Number.Uint64()
|
||||||
|
|
||||||
var known bool
|
var known bool
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ type BlockChain interface {
|
||||||
// InsertChain inserts a batch of blocks into the local chain.
|
// InsertChain inserts a batch of blocks into the local chain.
|
||||||
InsertChain(types.Blocks) (int, error)
|
InsertChain(types.Blocks) (int, error)
|
||||||
|
|
||||||
// InterruptInsert whether disables the chain insertion.
|
// InterruptInsert disables or enables chain insertion.
|
||||||
InterruptInsert(on bool)
|
InterruptInsert(on bool)
|
||||||
|
|
||||||
// InsertReceiptChain inserts a batch of blocks along with their receipts
|
// InsertReceiptChain inserts a batch of blocks along with their receipts
|
||||||
|
|
@ -513,7 +513,7 @@ func (d *Downloader) syncToHead() (err error) {
|
||||||
//
|
//
|
||||||
// For non-merged networks, if there is a checkpoint available, then calculate
|
// For non-merged networks, if there is a checkpoint available, then calculate
|
||||||
// the ancientLimit through that. Otherwise calculate the ancient limit through
|
// the ancientLimit through that. Otherwise calculate the ancient limit through
|
||||||
// the advertised height of the remote peer. This most is mostly a fallback for
|
// the advertised height of the remote peer. This is mostly a fallback for
|
||||||
// legacy networks, but should eventually be dropped. TODO(karalabe).
|
// legacy networks, but should eventually be dropped. TODO(karalabe).
|
||||||
//
|
//
|
||||||
// Beacon sync, use the latest finalized block as the ancient limit
|
// Beacon sync, use the latest finalized block as the ancient limit
|
||||||
|
|
@ -535,9 +535,15 @@ func (d *Downloader) syncToHead() (err error) {
|
||||||
|
|
||||||
// If a part of blockchain data has already been written into active store,
|
// If a part of blockchain data has already been written into active store,
|
||||||
// disable the ancient style insertion explicitly.
|
// disable the ancient style insertion explicitly.
|
||||||
if origin >= frozen && frozen != 0 {
|
if origin >= frozen && origin != 0 {
|
||||||
d.ancientLimit = 0
|
d.ancientLimit = 0
|
||||||
log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", frozen-1)
|
var ancient string
|
||||||
|
if frozen == 0 {
|
||||||
|
ancient = "null"
|
||||||
|
} else {
|
||||||
|
ancient = fmt.Sprintf("%d", frozen-1)
|
||||||
|
}
|
||||||
|
log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", ancient)
|
||||||
} else if d.ancientLimit > 0 {
|
} else if d.ancientLimit > 0 {
|
||||||
log.Debug("Enabling direct-ancient mode", "ancient", d.ancientLimit)
|
log.Debug("Enabling direct-ancient mode", "ancient", d.ancientLimit)
|
||||||
}
|
}
|
||||||
|
|
@ -940,7 +946,7 @@ func (d *Downloader) processSnapSyncContent() error {
|
||||||
if !d.committed.Load() {
|
if !d.committed.Load() {
|
||||||
latest := results[len(results)-1].Header
|
latest := results[len(results)-1].Header
|
||||||
// If the height is above the pivot block by 2 sets, it means the pivot
|
// If the height is above the pivot block by 2 sets, it means the pivot
|
||||||
// become stale in the network, and it was garbage collected, move to a
|
// became stale in the network, and it was garbage collected, move to a
|
||||||
// new pivot.
|
// new pivot.
|
||||||
//
|
//
|
||||||
// Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
|
// Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
|
||||||
|
|
@ -1037,7 +1043,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
|
||||||
first, last := results[0].Header, results[len(results)-1].Header
|
first, last := results[0].Header, results[len(results)-1].Header
|
||||||
log.Debug("Inserting snap-sync blocks", "items", len(results),
|
log.Debug("Inserting snap-sync blocks", "items", len(results),
|
||||||
"firstnum", first.Number, "firsthash", first.Hash(),
|
"firstnum", first.Number, "firsthash", first.Hash(),
|
||||||
"lastnumn", last.Number, "lasthash", last.Hash(),
|
"lastnum", last.Number, "lasthash", last.Hash(),
|
||||||
)
|
)
|
||||||
blocks := make([]*types.Block, len(results))
|
blocks := make([]*types.Block, len(results))
|
||||||
receipts := make([]rlp.RawValue, len(results))
|
receipts := make([]rlp.RawValue, len(results))
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
|
||||||
tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:])
|
tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:])
|
||||||
|
|
||||||
if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil {
|
if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil {
|
||||||
t.Fatalf("failed to start beacon sync: #{err}")
|
t.Fatalf("failed to start beacon sync: %v", err)
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-complete:
|
case <-complete:
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,6 @@ func (d *Downloader) fetchHeadersByHash(p *peerConnection, hash common.Hash, amo
|
||||||
defer timeoutTimer.Stop()
|
defer timeoutTimer.Stop()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-d.cancelCh:
|
|
||||||
return nil, nil, errCanceled
|
|
||||||
|
|
||||||
case <-timeoutTimer.C:
|
case <-timeoutTimer.C:
|
||||||
// Header retrieval timed out, update the metrics
|
// Header retrieval timed out, update the metrics
|
||||||
p.log.Debug("Header request timed out", "elapsed", ttl)
|
p.log.Debug("Header request timed out", "elapsed", ttl)
|
||||||
|
|
|
||||||
|
|
@ -1150,6 +1150,9 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
|
||||||
if number < s.progress.Subchains[0].Head {
|
if number < s.progress.Subchains[0].Head {
|
||||||
// The skeleton chain is partially consumed, set the new tail as filled+1.
|
// The skeleton chain is partially consumed, set the new tail as filled+1.
|
||||||
tail := rawdb.ReadSkeletonHeader(s.db, number+1)
|
tail := rawdb.ReadSkeletonHeader(s.db, number+1)
|
||||||
|
if tail == nil {
|
||||||
|
return fmt.Errorf("filled header is missing: %d", number+1)
|
||||||
|
}
|
||||||
if tail.ParentHash != filled.Hash() {
|
if tail.ParentHash != filled.Hash() {
|
||||||
return fmt.Errorf("filled header is discontinuous with subchain: %d %s, please file an issue", number, filled.Hash())
|
return fmt.Errorf("filled header is discontinuous with subchain: %d %s, please file an issue", number, filled.Hash())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
package ethconfig
|
package ethconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -154,7 +154,7 @@ type Config struct {
|
||||||
// RPCEVMTimeout is the global timeout for eth-call.
|
// RPCEVMTimeout is the global timeout for eth-call.
|
||||||
RPCEVMTimeout time.Duration
|
RPCEVMTimeout time.Duration
|
||||||
|
|
||||||
// RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for
|
// RPCTxFeeCap is the global transaction fee (price * gas limit) cap for
|
||||||
// send-transaction variants. The unit is ether.
|
// send-transaction variants. The unit is ether.
|
||||||
RPCTxFeeCap float64
|
RPCTxFeeCap float64
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ type Config struct {
|
||||||
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
|
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
|
||||||
if config.TerminalTotalDifficulty == nil {
|
if config.TerminalTotalDifficulty == nil {
|
||||||
log.Error("Geth only supports PoS networks. Please transition legacy networks using Geth v1.13.x.")
|
log.Error("Geth only supports PoS networks. Please transition legacy networks using Geth v1.13.x.")
|
||||||
return nil, fmt.Errorf("'terminalTotalDifficulty' is not set in genesis block")
|
return nil, errors.New("'terminalTotalDifficulty' is not set in genesis block")
|
||||||
}
|
}
|
||||||
// Wrap previously supported consensus engines into their post-merge counterpart
|
// Wrap previously supported consensus engines into their post-merge counterpart
|
||||||
if config.Clique != nil {
|
if config.Clique != nil {
|
||||||
|
|
|
||||||
|
|
@ -439,8 +439,8 @@ func (f *TxFetcher) loop() {
|
||||||
if want > maxTxAnnounces {
|
if want > maxTxAnnounces {
|
||||||
txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces))
|
txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces))
|
||||||
|
|
||||||
ann.hashes = ann.hashes[:want-maxTxAnnounces]
|
ann.hashes = ann.hashes[:maxTxAnnounces-used]
|
||||||
ann.metas = ann.metas[:want-maxTxAnnounces]
|
ann.metas = ann.metas[:maxTxAnnounces-used]
|
||||||
}
|
}
|
||||||
// All is well, schedule the remainder of the transactions
|
// All is well, schedule the remainder of the transactions
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -1179,6 +1179,24 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
|
||||||
size: 111,
|
size: 111,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
hashesC []common.Hash
|
||||||
|
typesC []byte
|
||||||
|
sizesC []uint32
|
||||||
|
announceC []announce
|
||||||
|
)
|
||||||
|
for i := 0; i < maxTxAnnounces+2; i++ {
|
||||||
|
hash := common.Hash{0x03, byte(i / 256), byte(i % 256)}
|
||||||
|
hashesC = append(hashesC, hash)
|
||||||
|
typesC = append(typesC, types.LegacyTxType)
|
||||||
|
sizesC = append(sizesC, 111)
|
||||||
|
|
||||||
|
announceC = append(announceC, announce{
|
||||||
|
hash: hash,
|
||||||
|
kind: types.LegacyTxType,
|
||||||
|
size: 111,
|
||||||
|
})
|
||||||
|
}
|
||||||
testTransactionFetcherParallel(t, txFetcherTest{
|
testTransactionFetcherParallel(t, txFetcherTest{
|
||||||
init: func() *TxFetcher {
|
init: func() *TxFetcher {
|
||||||
return NewTxFetcher(
|
return NewTxFetcher(
|
||||||
|
|
@ -1192,43 +1210,52 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
|
||||||
// Announce half of the transaction and wait for them to be scheduled
|
// Announce half of the transaction and wait for them to be scheduled
|
||||||
doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2], types: typesA[:maxTxAnnounces/2], sizes: sizesA[:maxTxAnnounces/2]},
|
doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2], types: typesA[:maxTxAnnounces/2], sizes: sizesA[:maxTxAnnounces/2]},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1], types: typesB[:maxTxAnnounces/2-1], sizes: sizesB[:maxTxAnnounces/2-1]},
|
doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1], types: typesB[:maxTxAnnounces/2-1], sizes: sizesB[:maxTxAnnounces/2-1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[:maxTxAnnounces/2-1], types: typesC[:maxTxAnnounces/2-1], sizes: sizesC[:maxTxAnnounces/2-1]},
|
||||||
doWait{time: txArriveTimeout, step: true},
|
doWait{time: txArriveTimeout, step: true},
|
||||||
|
|
||||||
// Announce the second half and keep them in the wait list
|
// Announce the second half and keep them in the wait list
|
||||||
doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces], types: typesA[maxTxAnnounces/2 : maxTxAnnounces], sizes: sizesA[maxTxAnnounces/2 : maxTxAnnounces]},
|
doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces], types: typesA[maxTxAnnounces/2 : maxTxAnnounces], sizes: sizesA[maxTxAnnounces/2 : maxTxAnnounces]},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesC[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesC[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
||||||
|
|
||||||
// Ensure the hashes are split half and half
|
// Ensure the hashes are split half and half
|
||||||
isWaiting(map[string][]announce{
|
isWaiting(map[string][]announce{
|
||||||
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
||||||
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
||||||
|
"C": announceC[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
||||||
}),
|
}),
|
||||||
isScheduled{
|
isScheduled{
|
||||||
tracking: map[string][]announce{
|
tracking: map[string][]announce{
|
||||||
"A": announceA[:maxTxAnnounces/2],
|
"A": announceA[:maxTxAnnounces/2],
|
||||||
"B": announceB[:maxTxAnnounces/2-1],
|
"B": announceB[:maxTxAnnounces/2-1],
|
||||||
|
"C": announceC[:maxTxAnnounces/2-1],
|
||||||
},
|
},
|
||||||
fetching: map[string][]common.Hash{
|
fetching: map[string][]common.Hash{
|
||||||
"A": hashesA[:maxTxRetrievals],
|
"A": hashesA[:maxTxRetrievals],
|
||||||
"B": hashesB[:maxTxRetrievals],
|
"B": hashesB[:maxTxRetrievals],
|
||||||
|
"C": hashesC[:maxTxRetrievals],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Ensure that adding even one more hash results in dropping the hash
|
// Ensure that adding even one more hash results in dropping the hash
|
||||||
doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}, types: []byte{typesA[maxTxAnnounces]}, sizes: []uint32{sizesA[maxTxAnnounces]}},
|
doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}, types: []byte{typesA[maxTxAnnounces]}, sizes: []uint32{sizesA[maxTxAnnounces]}},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1], types: typesB[maxTxAnnounces-1 : maxTxAnnounces+1], sizes: sizesB[maxTxAnnounces-1 : maxTxAnnounces+1]},
|
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1], types: typesB[maxTxAnnounces-1 : maxTxAnnounces+1], sizes: sizesB[maxTxAnnounces-1 : maxTxAnnounces+1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[maxTxAnnounces-1 : maxTxAnnounces+2], types: typesC[maxTxAnnounces-1 : maxTxAnnounces+2], sizes: sizesC[maxTxAnnounces-1 : maxTxAnnounces+2]},
|
||||||
|
|
||||||
isWaiting(map[string][]announce{
|
isWaiting(map[string][]announce{
|
||||||
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
||||||
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces],
|
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces],
|
||||||
|
"C": announceC[maxTxAnnounces/2-1 : maxTxAnnounces],
|
||||||
}),
|
}),
|
||||||
isScheduled{
|
isScheduled{
|
||||||
tracking: map[string][]announce{
|
tracking: map[string][]announce{
|
||||||
"A": announceA[:maxTxAnnounces/2],
|
"A": announceA[:maxTxAnnounces/2],
|
||||||
"B": announceB[:maxTxAnnounces/2-1],
|
"B": announceB[:maxTxAnnounces/2-1],
|
||||||
|
"C": announceC[:maxTxAnnounces/2-1],
|
||||||
},
|
},
|
||||||
fetching: map[string][]common.Hash{
|
fetching: map[string][]common.Hash{
|
||||||
"A": hashesA[:maxTxRetrievals],
|
"A": hashesA[:maxTxRetrievals],
|
||||||
"B": hashesB[:maxTxRetrievals],
|
"B": hashesB[:maxTxRetrievals],
|
||||||
|
"C": hashesC[:maxTxRetrievals],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ var (
|
||||||
errInvalidTopic = errors.New("invalid topic(s)")
|
errInvalidTopic = errors.New("invalid topic(s)")
|
||||||
errFilterNotFound = errors.New("filter not found")
|
errFilterNotFound = errors.New("filter not found")
|
||||||
errInvalidBlockRange = errors.New("invalid block range params")
|
errInvalidBlockRange = errors.New("invalid block range params")
|
||||||
|
errUnknownBlock = errors.New("unknown block")
|
||||||
|
errBlockHashWithRange = errors.New("can't specify fromBlock/toBlock with blockHash")
|
||||||
errPendingLogsUnsupported = errors.New("pending logs are not supported")
|
errPendingLogsUnsupported = errors.New("pending logs are not supported")
|
||||||
errExceedMaxTopics = errors.New("exceed max topics")
|
errExceedMaxTopics = errors.New("exceed max topics")
|
||||||
errExceedMaxAddresses = errors.New("exceed max addresses")
|
errExceedMaxAddresses = errors.New("exceed max addresses")
|
||||||
|
|
@ -348,8 +350,13 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
|
||||||
if len(crit.Addresses) > maxAddresses {
|
if len(crit.Addresses) > maxAddresses {
|
||||||
return nil, errExceedMaxAddresses
|
return nil, errExceedMaxAddresses
|
||||||
}
|
}
|
||||||
|
|
||||||
var filter *Filter
|
var filter *Filter
|
||||||
if crit.BlockHash != nil {
|
if crit.BlockHash != nil {
|
||||||
|
if crit.FromBlock != nil || crit.ToBlock != nil {
|
||||||
|
return nil, errBlockHashWithRange
|
||||||
|
}
|
||||||
|
|
||||||
// Block filter requested, construct a single-shot filter
|
// Block filter requested, construct a single-shot filter
|
||||||
filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics)
|
filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -372,6 +379,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
|
||||||
// Construct the range filter
|
// Construct the range filter
|
||||||
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
|
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the filter and return all the logs
|
// Run the filter and return all the logs
|
||||||
logs, err := filter.Logs(ctx)
|
logs, err := filter.Logs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errors.New("unknown block")
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
if header.Number.Uint64() < f.sys.backend.HistoryPruningCutoff() {
|
if header.Number.Uint64() < f.sys.backend.HistoryPruningCutoff() {
|
||||||
return nil, &history.PrunedHistoryError{}
|
return nil, &history.PrunedHistoryError{}
|
||||||
|
|
@ -456,7 +456,6 @@ func (f *Filter) blockLogs(ctx context.Context, header *types.Header) ([]*types.
|
||||||
|
|
||||||
// checkMatches checks if the receipts belonging to the given header contain any log events that
|
// checkMatches checks if the receipts belonging to the given header contain any log events that
|
||||||
// match the filter criteria. This function is called when the bloom filter signals a potential match.
|
// match the filter criteria. This function is called when the bloom filter signals a potential match.
|
||||||
// skipFilter signals all logs of the given block are requested.
|
|
||||||
func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*types.Log, error) {
|
func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*types.Log, error) {
|
||||||
hash := header.Hash()
|
hash := header.Hash()
|
||||||
// Logs in cache are partially filled with context data
|
// Logs in cache are partially filled with context data
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ type EventSystem struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEventSystem creates a new manager that listens for event on the given mux,
|
// NewEventSystem creates a new manager that listens for event on the given mux,
|
||||||
// parses and filters them. It uses the all map to retrieve filter changes. The
|
// parses and filters them. It uses an internal map to retrieve filter changes. The
|
||||||
// work loop holds its own index that is used to forward events to filters.
|
// work loop holds its own index that is used to forward events to filters.
|
||||||
//
|
//
|
||||||
// The returned manager has a loop that needs to be stopped with the Stop function
|
// The returned manager has a loop that needs to be stopped with the Stop function
|
||||||
|
|
|
||||||
|
|
@ -92,18 +92,18 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe
|
||||||
switch blockNr {
|
switch blockNr {
|
||||||
case rpc.LatestBlockNumber:
|
case rpc.LatestBlockNumber:
|
||||||
hash = rawdb.ReadHeadBlockHash(b.db)
|
hash = rawdb.ReadHeadBlockHash(b.db)
|
||||||
number := rawdb.ReadHeaderNumber(b.db, hash)
|
number, ok := rawdb.ReadHeaderNumber(b.db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
num = *number
|
num = number
|
||||||
case rpc.FinalizedBlockNumber:
|
case rpc.FinalizedBlockNumber:
|
||||||
hash = rawdb.ReadFinalizedBlockHash(b.db)
|
hash = rawdb.ReadFinalizedBlockHash(b.db)
|
||||||
number := rawdb.ReadHeaderNumber(b.db, hash)
|
number, ok := rawdb.ReadHeaderNumber(b.db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
num = *number
|
num = number
|
||||||
case rpc.SafeBlockNumber:
|
case rpc.SafeBlockNumber:
|
||||||
return nil, errors.New("safe block not found")
|
return nil, errors.New("safe block not found")
|
||||||
default:
|
default:
|
||||||
|
|
@ -114,11 +114,11 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
number := rawdb.ReadHeaderNumber(b.db, hash)
|
number, ok := rawdb.ReadHeaderNumber(b.db, hash)
|
||||||
if number == nil {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return rawdb.ReadHeader(b.db, hash, *number), nil
|
return rawdb.ReadHeader(b.db, hash, number), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
|
func (b *testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
|
||||||
|
|
@ -129,9 +129,9 @@ func (b *testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
|
func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
|
||||||
if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil {
|
if number, ok := rawdb.ReadHeaderNumber(b.db, hash); ok {
|
||||||
if header := rawdb.ReadHeader(b.db, hash, *number); header != nil {
|
if header := rawdb.ReadHeader(b.db, hash, number); header != nil {
|
||||||
return rawdb.ReadReceipts(b.db, hash, *number, header.Time, params.TestChainConfig), nil
|
return rawdb.ReadReceipts(b.db, hash, number, header.Time, params.TestChainConfig), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -450,24 +450,65 @@ func TestInvalidGetLogsRequest(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
db = rawdb.NewMemoryDatabase()
|
genesis = &core.Genesis{
|
||||||
_, sys = newTestFilterSystem(db, Config{})
|
Config: params.TestChainConfig,
|
||||||
api = NewFilterAPI(sys)
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
}
|
||||||
|
db, blocks, _ = core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 10, func(i int, gen *core.BlockGen) {})
|
||||||
|
_, sys = newTestFilterSystem(db, Config{})
|
||||||
|
api = NewFilterAPI(sys)
|
||||||
|
blockHash = blocks[0].Hash()
|
||||||
|
unknownBlockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reason: Cannot specify both BlockHash and FromBlock/ToBlock)
|
// Insert the blocks into the chain so filter can look them up
|
||||||
testCases := []FilterCriteria{
|
blockchain, err := core.NewBlockChain(db, genesis, ethash.NewFaker(), nil)
|
||||||
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
if err != nil {
|
||||||
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
}
|
||||||
3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
if n, err := blockchain.InsertChain(blocks); err != nil {
|
||||||
4: {BlockHash: &blockHash, Addresses: make([]common.Address, maxAddresses+1)},
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type testcase struct {
|
||||||
|
f FilterCriteria
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
testCases := []testcase{
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
||||||
|
err: errBlockHashWithRange,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, ToBlock: big.NewInt(500)},
|
||||||
|
err: errBlockHashWithRange,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||||
|
err: errBlockHashWithRange,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &unknownBlockHash},
|
||||||
|
err: errUnknownBlock,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
||||||
|
err: errExceedMaxTopics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
||||||
|
err: errExceedMaxTopics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f: FilterCriteria{BlockHash: &blockHash, Addresses: make([]common.Address, maxAddresses+1)},
|
||||||
|
err: errExceedMaxAddresses,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range testCases {
|
for i, test := range testCases {
|
||||||
if _, err := api.GetLogs(context.Background(), test); err == nil {
|
_, err := api.GetLogs(context.Background(), test.f)
|
||||||
t.Errorf("Expected Logs for case #%d to fail", i)
|
if !errors.Is(err, test.err) {
|
||||||
|
t.Errorf("case %d: wrong error: %q\nwant: %q", i, err, test.err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mid := (hi + lo) / 2
|
mid := lo + (hi-lo)/2
|
||||||
if mid > lo*2 {
|
if mid > lo*2 {
|
||||||
// Most txs don't need much higher gas limit than their gas used, and most txs don't
|
// Most txs don't need much higher gas limit than their gas used, and most txs don't
|
||||||
// require near the full block limit of gas, so the selection of where to bisect the
|
// require near the full block limit of gas, so the selection of where to bisect the
|
||||||
|
|
|
||||||
|
|
@ -661,11 +661,7 @@ func testGetPooledTransaction(t *testing.T, blobTx bool) {
|
||||||
To: testAddr,
|
To: testAddr,
|
||||||
BlobHashes: []common.Hash{emptyBlobHash},
|
BlobHashes: []common.Hash{emptyBlobHash},
|
||||||
BlobFeeCap: uint256.MustFromBig(common.Big1),
|
BlobFeeCap: uint256.MustFromBig(common.Big1),
|
||||||
Sidecar: &types.BlobTxSidecar{
|
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion0, emptyBlobs, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof}),
|
||||||
Blobs: emptyBlobs,
|
|
||||||
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
|
||||||
Proofs: []kzg4844.Proof{emptyBlobProof},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -66,4 +66,7 @@ var (
|
||||||
// discarded during the snap sync.
|
// discarded during the snap sync.
|
||||||
largeStorageDiscardGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/discard", nil)
|
largeStorageDiscardGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/discard", nil)
|
||||||
largeStorageResumedGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/resume", nil)
|
largeStorageResumedGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/resume", nil)
|
||||||
|
|
||||||
|
stateSyncTimeGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/time/statesync", nil)
|
||||||
|
stateHealTimeGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/time/stateheal", nil)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -502,8 +502,10 @@ type Syncer struct {
|
||||||
storageHealed uint64 // Number of storage slots downloaded during the healing stage
|
storageHealed uint64 // Number of storage slots downloaded during the healing stage
|
||||||
storageHealedBytes common.StorageSize // Number of raw storage bytes persisted to disk during the healing stage
|
storageHealedBytes common.StorageSize // Number of raw storage bytes persisted to disk during the healing stage
|
||||||
|
|
||||||
startTime time.Time // Time instance when snapshot sync started
|
startTime time.Time // Time instance when snapshot sync started
|
||||||
logTime time.Time // Time instance when status was last reported
|
healStartTime time.Time // Time instance when the state healing started
|
||||||
|
syncTimeOnce sync.Once // Ensure that the state sync time is uploaded only once
|
||||||
|
logTime time.Time // Time instance when status was last reported
|
||||||
|
|
||||||
pend sync.WaitGroup // Tracks network request goroutines for graceful shutdown
|
pend sync.WaitGroup // Tracks network request goroutines for graceful shutdown
|
||||||
lock sync.RWMutex // Protects fields that can change outside of sync (peers, reqs, root)
|
lock sync.RWMutex // Protects fields that can change outside of sync (peers, reqs, root)
|
||||||
|
|
@ -615,7 +617,7 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
|
||||||
s.statelessPeers = make(map[string]struct{})
|
s.statelessPeers = make(map[string]struct{})
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
|
|
||||||
if s.startTime == (time.Time{}) {
|
if s.startTime.IsZero() {
|
||||||
s.startTime = time.Now()
|
s.startTime = time.Now()
|
||||||
}
|
}
|
||||||
// Retrieve the previous sync status from LevelDB and abort if already synced
|
// Retrieve the previous sync status from LevelDB and abort if already synced
|
||||||
|
|
@ -685,6 +687,14 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
|
||||||
s.cleanStorageTasks()
|
s.cleanStorageTasks()
|
||||||
s.cleanAccountTasks()
|
s.cleanAccountTasks()
|
||||||
if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 {
|
if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 {
|
||||||
|
// State healing phase completed, record the elapsed time in metrics.
|
||||||
|
// Note: healing may be rerun in subsequent cycles to fill gaps between
|
||||||
|
// pivot states (e.g., if chain sync takes longer).
|
||||||
|
if !s.healStartTime.IsZero() {
|
||||||
|
stateHealTimeGauge.Inc(int64(time.Since(s.healStartTime)))
|
||||||
|
log.Info("State healing phase is completed", "elapsed", common.PrettyDuration(time.Since(s.healStartTime)))
|
||||||
|
s.healStartTime = time.Time{}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Assign all the data retrieval tasks to any free peers
|
// Assign all the data retrieval tasks to any free peers
|
||||||
|
|
@ -693,7 +703,17 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
|
||||||
s.assignStorageTasks(storageResps, storageReqFails, cancel)
|
s.assignStorageTasks(storageResps, storageReqFails, cancel)
|
||||||
|
|
||||||
if len(s.tasks) == 0 {
|
if len(s.tasks) == 0 {
|
||||||
// Sync phase done, run heal phase
|
// State sync phase completed, record the elapsed time in metrics.
|
||||||
|
// Note: the initial state sync runs only once, regardless of whether
|
||||||
|
// a new cycle is started later. Any state differences in subsequent
|
||||||
|
// cycles will be handled by the state healer.
|
||||||
|
s.syncTimeOnce.Do(func() {
|
||||||
|
stateSyncTimeGauge.Update(int64(time.Since(s.startTime)))
|
||||||
|
log.Info("State sync phase is completed", "elapsed", common.PrettyDuration(time.Since(s.startTime)))
|
||||||
|
})
|
||||||
|
if s.healStartTime.IsZero() {
|
||||||
|
s.healStartTime = time.Now()
|
||||||
|
}
|
||||||
s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
|
s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
|
||||||
s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
|
s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
|
||||||
}
|
}
|
||||||
|
|
@ -1987,9 +2007,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
|
||||||
func (s *Syncer) processBytecodeResponse(res *bytecodeResponse) {
|
func (s *Syncer) processBytecodeResponse(res *bytecodeResponse) {
|
||||||
batch := s.db.NewBatch()
|
batch := s.db.NewBatch()
|
||||||
|
|
||||||
var (
|
var codes uint64
|
||||||
codes uint64
|
|
||||||
)
|
|
||||||
for i, hash := range res.hashes {
|
for i, hash := range res.hashes {
|
||||||
code := res.codes[i]
|
code := res.codes[i]
|
||||||
|
|
||||||
|
|
@ -3113,6 +3131,10 @@ func (s *Syncer) reportSyncProgress(force bool) {
|
||||||
if estBytes < 1.0 {
|
if estBytes < 1.0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Cap the estimated state size using the synced size to avoid negative values
|
||||||
|
if estBytes < float64(synced) {
|
||||||
|
estBytes = float64(synced)
|
||||||
|
}
|
||||||
elapsed := time.Since(s.startTime)
|
elapsed := time.Since(s.startTime)
|
||||||
estTime := elapsed / time.Duration(synced) * time.Duration(estBytes)
|
estTime := elapsed / time.Duration(synced) * time.Duration(estBytes)
|
||||||
|
|
||||||
|
|
|
||||||
197
eth/syncer/syncer.go
Normal file
197
eth/syncer/syncer.go
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
// Copyright 2025 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 syncer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type syncReq struct {
|
||||||
|
hash common.Hash
|
||||||
|
errc chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Syncer is an auxiliary service that allows Geth to perform full sync
|
||||||
|
// alone without consensus-layer attached. Users must specify a valid block hash
|
||||||
|
// as the sync target.
|
||||||
|
//
|
||||||
|
// This tool can be applied to different networks, no matter it's pre-merge or
|
||||||
|
// post-merge, but only for full-sync.
|
||||||
|
type Syncer struct {
|
||||||
|
stack *node.Node
|
||||||
|
backend *eth.Ethereum
|
||||||
|
target common.Hash
|
||||||
|
request chan *syncReq
|
||||||
|
closed chan struct{}
|
||||||
|
wg sync.WaitGroup
|
||||||
|
exitWhenSynced bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register registers the synchronization override service into the node
|
||||||
|
// stack for launching and stopping the service controlled by node.
|
||||||
|
func Register(stack *node.Node, backend *eth.Ethereum, target common.Hash, exitWhenSynced bool) (*Syncer, error) {
|
||||||
|
s := &Syncer{
|
||||||
|
stack: stack,
|
||||||
|
backend: backend,
|
||||||
|
target: target,
|
||||||
|
request: make(chan *syncReq),
|
||||||
|
closed: make(chan struct{}),
|
||||||
|
exitWhenSynced: exitWhenSynced,
|
||||||
|
}
|
||||||
|
stack.RegisterAPIs(s.APIs())
|
||||||
|
stack.RegisterLifecycle(s)
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIs return the collection of RPC services the ethereum package offers.
|
||||||
|
// NOTE, some of these services probably need to be moved to somewhere else.
|
||||||
|
func (s *Syncer) APIs() []rpc.API {
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
|
Namespace: "debug",
|
||||||
|
Service: NewAPI(s),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// run is the main loop that monitors sync requests from users and initiates
|
||||||
|
// sync operations when necessary. It also checks whether the specified target
|
||||||
|
// has been reached and shuts down Geth if requested by the user.
|
||||||
|
func (s *Syncer) run() {
|
||||||
|
defer s.wg.Done()
|
||||||
|
|
||||||
|
var (
|
||||||
|
target *types.Header
|
||||||
|
ticker = time.NewTicker(time.Second * 5)
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case req := <-s.request:
|
||||||
|
var (
|
||||||
|
resync bool
|
||||||
|
retries int
|
||||||
|
logged bool
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
if retries >= 10 {
|
||||||
|
req.errc <- fmt.Errorf("sync target is not avaibale, %x", req.hash)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-s.closed:
|
||||||
|
req.errc <- errors.New("syncer closed")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
header, err := s.backend.Downloader().GetHeader(req.hash)
|
||||||
|
if err != nil {
|
||||||
|
if !logged {
|
||||||
|
logged = true
|
||||||
|
log.Info("Waiting for peers to retrieve sync target", "hash", req.hash)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * time.Duration(retries+1))
|
||||||
|
retries++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if target != nil && header.Number.Cmp(target.Number) <= 0 {
|
||||||
|
req.errc <- fmt.Errorf("stale sync target, current: %d, received: %d", target.Number, header.Number)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
target = header
|
||||||
|
resync = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if resync {
|
||||||
|
req.errc <- s.backend.Downloader().BeaconDevSync(ethconfig.FullSync, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-ticker.C:
|
||||||
|
if target == nil || !s.exitWhenSynced {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if block := s.backend.BlockChain().GetBlockByHash(target.Hash()); block != nil {
|
||||||
|
log.Info("Sync target reached", "number", block.NumberU64(), "hash", block.Hash())
|
||||||
|
go s.stack.Close() // async since we need to close ourselves
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-s.closed:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start launches the synchronization service.
|
||||||
|
func (s *Syncer) Start() error {
|
||||||
|
s.wg.Add(1)
|
||||||
|
go s.run()
|
||||||
|
if s.target == (common.Hash{}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return s.Sync(s.target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop terminates the synchronization service and stop all background activities.
|
||||||
|
// This function can only be called for one time.
|
||||||
|
func (s *Syncer) Stop() error {
|
||||||
|
close(s.closed)
|
||||||
|
s.wg.Wait()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync sets the synchronization target. Notably, setting a target lower than the
|
||||||
|
// previous one is not allowed, as backward synchronization is not supported.
|
||||||
|
func (s *Syncer) Sync(hash common.Hash) error {
|
||||||
|
req := &syncReq{
|
||||||
|
hash: hash,
|
||||||
|
errc: make(chan error, 1),
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case s.request <- req:
|
||||||
|
return <-req.errc
|
||||||
|
case <-s.closed:
|
||||||
|
return errors.New("syncer is closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// API is the collection of synchronization service APIs for debugging the
|
||||||
|
// protocol.
|
||||||
|
type API struct {
|
||||||
|
s *Syncer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAPI creates a new debug API instance.
|
||||||
|
func NewAPI(s *Syncer) *API {
|
||||||
|
return &API{s: s}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync initiates a full sync to the target block hash.
|
||||||
|
func (api *API) Sync(target common.Hash) error {
|
||||||
|
return api.s.Sync(target)
|
||||||
|
}
|
||||||
|
|
@ -953,40 +953,53 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
}
|
}
|
||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
h := block.Header()
|
||||||
|
blockContext := core.NewEVMBlockContext(h, api.chainContext(ctx), nil)
|
||||||
|
|
||||||
// Apply the customization rules if required.
|
// Apply the customization rules if required.
|
||||||
if config != nil {
|
if config != nil {
|
||||||
if overrideErr := config.BlockOverrides.Apply(&vmctx); overrideErr != nil {
|
if config.BlockOverrides != nil && config.BlockOverrides.Number.ToInt().Uint64() == h.Number.Uint64()+1 {
|
||||||
return nil, overrideErr
|
// Overriding the block number to n+1 is a common way for wallets to
|
||||||
|
// simulate transactions, however without the following fix, a contract
|
||||||
|
// can assert it is being simulated by checking if blockhash(n) == 0x0 and
|
||||||
|
// can behave differently during the simulation. (#32175 for more info)
|
||||||
|
// --
|
||||||
|
// Modify the parent hash and number so that downstream, blockContext's
|
||||||
|
// GetHash function can correctly return n.
|
||||||
|
h.ParentHash = h.Hash()
|
||||||
|
h.Number.Add(h.Number, big.NewInt(1))
|
||||||
}
|
}
|
||||||
rules := api.backend.ChainConfig().Rules(vmctx.BlockNumber, vmctx.Random != nil, vmctx.Time)
|
if err := config.BlockOverrides.Apply(&blockContext); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rules := api.backend.ChainConfig().Rules(blockContext.BlockNumber, blockContext.Random != nil, blockContext.Time)
|
||||||
precompiles = vm.ActivePrecompiledContracts(rules)
|
precompiles = vm.ActivePrecompiledContracts(rules)
|
||||||
if err := config.StateOverrides.Apply(statedb, precompiles); err != nil {
|
if err := config.StateOverrides.Apply(statedb, precompiles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Execute the trace
|
|
||||||
if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID); err != nil {
|
// Execute the trace.
|
||||||
|
if err := args.CallDefaults(api.backend.RPCGasCap(), blockContext.BaseFee, api.backend.ChainConfig().ChainID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
msg = args.ToMessage(vmctx.BaseFee, true, true)
|
msg = args.ToMessage(blockContext.BaseFee, true, true)
|
||||||
tx = args.ToTransaction(types.LegacyTxType)
|
tx = args.ToTransaction(types.LegacyTxType)
|
||||||
traceConfig *TraceConfig
|
traceConfig *TraceConfig
|
||||||
)
|
)
|
||||||
// Lower the basefee to 0 to avoid breaking EVM
|
// Lower the basefee to 0 to avoid breaking EVM
|
||||||
// invariants (basefee < feecap).
|
// invariants (basefee < feecap).
|
||||||
if msg.GasPrice.Sign() == 0 {
|
if msg.GasPrice.Sign() == 0 {
|
||||||
vmctx.BaseFee = new(big.Int)
|
blockContext.BaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
||||||
vmctx.BlobBaseFee = new(big.Int)
|
blockContext.BlobBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
if config != nil {
|
if config != nil {
|
||||||
traceConfig = &config.TraceConfig
|
traceConfig = &config.TraceConfig
|
||||||
}
|
}
|
||||||
return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig, precompiles)
|
return api.traceTx(ctx, tx, msg, new(Context), blockContext, statedb, traceConfig, precompiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// traceTx configures a new tracer according to the provided configuration, and
|
// traceTx configures a new tracer according to the provided configuration, and
|
||||||
|
|
|
||||||
|
|
@ -689,6 +689,7 @@ func TestTracingWithOverrides(t *testing.T) {
|
||||||
Failed bool
|
Failed bool
|
||||||
ReturnValue string
|
ReturnValue string
|
||||||
}
|
}
|
||||||
|
|
||||||
var testSuite = []struct {
|
var testSuite = []struct {
|
||||||
blockNumber rpc.BlockNumber
|
blockNumber rpc.BlockNumber
|
||||||
call ethapi.TransactionArgs
|
call ethapi.TransactionArgs
|
||||||
|
|
@ -788,6 +789,25 @@ func TestTracingWithOverrides(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: `{"gas":72666,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
|
want: `{"gas":72666,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
|
||||||
},
|
},
|
||||||
|
{ // Override blocknumber with block n+1 and query a blockhash (resolves issue #32175)
|
||||||
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &accounts[0].addr,
|
||||||
|
Input: newRPCBytes([]byte{
|
||||||
|
byte(vm.PUSH1), byte(genBlocks),
|
||||||
|
byte(vm.BLOCKHASH),
|
||||||
|
byte(vm.PUSH1), 0x00,
|
||||||
|
byte(vm.MSTORE),
|
||||||
|
byte(vm.PUSH1), 0x20,
|
||||||
|
byte(vm.PUSH1), 0x00,
|
||||||
|
byte(vm.RETURN),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
config: &TraceCallConfig{
|
||||||
|
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(int64(genBlocks + 1)))},
|
||||||
|
},
|
||||||
|
want: fmt.Sprintf(`{"gas":59590,"failed":false,"returnValue":"%s"}`, backend.chain.GetHeaderByNumber(uint64(genBlocks)).Hash().Hex()),
|
||||||
|
},
|
||||||
/*
|
/*
|
||||||
pragma solidity =0.8.12;
|
pragma solidity =0.8.12;
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue