diff --git a/.travis.yml b/.travis.yml index 31c944641f..2ba3af9419 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ jobs: before_install: - export DOCKER_CLI_EXPERIMENTAL=enabled script: - - go run build/ci.go dockerx -platform "linux/amd64,linux/arm64" -upload ethereum/client-go + - go run build/ci.go dockerx -platform "linux/amd64,linux/arm64,linux/riscv64" -upload ethereum/client-go # This builder does the Linux Azure uploads - stage: build diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go index 81836b3717..2be6edd44f 100644 --- a/accounts/usbwallet/ledger.go +++ b/accounts/usbwallet/ledger.go @@ -338,8 +338,22 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction return common.Address{}, nil, err } } else { - if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil { - return common.Address{}, nil, err + if tx.Type() == types.DynamicFeeTxType { + if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil { + return common.Address{}, nil, err + } + // append type to transaction + txrlp = append([]byte{tx.Type()}, txrlp...) + } else if tx.Type() == types.AccessListTxType { + if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil { + return common.Address{}, nil, err + } + // append type to transaction + txrlp = append([]byte{tx.Type()}, txrlp...) + } else if tx.Type() == types.LegacyTxType { + if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil { + return common.Address{}, nil, err + } } } payload := append(path, txrlp...) @@ -353,7 +367,9 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app. // https://github.com/LedgerHQ/app-ethereum/issues/409 chunk := 255 - for ; len(payload)%chunk <= ledgerEip155Size; chunk-- { + if tx.Type() == types.LegacyTxType { + for ; len(payload)%chunk <= ledgerEip155Size; chunk-- { + } } for len(payload) > 0 { @@ -381,8 +397,11 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction if chainID == nil { signer = new(types.HomesteadSigner) } else { - signer = types.NewEIP155Signer(chainID) - signature[64] -= byte(chainID.Uint64()*2 + 35) + signer = types.LatestSignerForChainID(chainID) + // For non-legacy transactions, V is 0 or 1, no need to subtract here. + if tx.Type() == types.LegacyTxType { + signature[64] -= byte(chainID.Uint64()*2 + 35) + } } signed, err := tx.WithSignature(signer, signature) if err != nil { diff --git a/appveyor.yml b/appveyor.yml index 92369537cd..1543211edc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,9 @@ for: - image: Ubuntu build_script: - go run build/ci.go lint - - go run build/ci.go generate -verify + - go run build/ci.go check_tidy + - go run build/ci.go check_generate + - go run build/ci.go check_baddeps - go run build/ci.go install -dlgo test_script: - go run build/ci.go test -dlgo -short diff --git a/beacon/blsync/client.go b/beacon/blsync/client.go index 39a1c6ea76..3c93754d3d 100644 --- a/beacon/blsync/client.go +++ b/beacon/blsync/client.go @@ -17,25 +17,22 @@ package blsync import ( - "strings" - "github.com/ethereum/go-ethereum/beacon/light" "github.com/ethereum/go-ethereum/beacon/light/api" "github.com/ethereum/go-ethereum/beacon/light/request" "github.com/ethereum/go-ethereum/beacon/light/sync" + "github.com/ethereum/go-ethereum/beacon/params" "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/rpc" - "github.com/urfave/cli/v2" ) type Client struct { urls []string customHeader map[string]string - chainConfig *lightClientConfig + config *params.ClientConfig scheduler *request.Scheduler blockSync *beaconBlockSync engineRPC *rpc.Client @@ -44,34 +41,18 @@ type Client struct { engineClient *engineClient } -func NewClient(ctx *cli.Context) *Client { - if !ctx.IsSet(utils.BeaconApiFlag.Name) { - utils.Fatalf("Beacon node light client API URL not specified") - } - var ( - chainConfig = makeChainConfig(ctx) - customHeader = make(map[string]string) - ) - for _, s := range ctx.StringSlice(utils.BeaconApiHeaderFlag.Name) { - kv := strings.Split(s, ":") - if len(kv) != 2 { - utils.Fatalf("Invalid custom API header entry: %s", s) - } - customHeader[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1]) - } - +func NewClient(config params.ClientConfig) *Client { // create data structures var ( db = memorydb.New() - threshold = ctx.Int(utils.BeaconThresholdFlag.Name) - committeeChain = light.NewCommitteeChain(db, chainConfig.ChainConfig, threshold, !ctx.Bool(utils.BeaconNoFilterFlag.Name)) - headTracker = light.NewHeadTracker(committeeChain, threshold) + committeeChain = light.NewCommitteeChain(db, &config.ChainConfig, config.Threshold, !config.NoFilter) + headTracker = light.NewHeadTracker(committeeChain, config.Threshold) ) headSync := sync.NewHeadSync(headTracker, committeeChain) // set up scheduler and sync modules scheduler := request.NewScheduler() - checkpointInit := sync.NewCheckpointInit(committeeChain, chainConfig.Checkpoint) + checkpointInit := sync.NewCheckpointInit(committeeChain, config.Checkpoint) forwardSync := sync.NewForwardUpdateSync(committeeChain) beaconBlockSync := newBeaconBlockSync(headTracker) scheduler.RegisterTarget(headTracker) @@ -83,9 +64,9 @@ func NewClient(ctx *cli.Context) *Client { return &Client{ scheduler: scheduler, - urls: ctx.StringSlice(utils.BeaconApiFlag.Name), - customHeader: customHeader, - chainConfig: &chainConfig, + urls: config.Apis, + customHeader: config.CustomHeader, + config: &config, blockSync: beaconBlockSync, } } @@ -97,7 +78,7 @@ func (c *Client) SetEngineRPC(engine *rpc.Client) { func (c *Client) Start() error { headCh := make(chan types.ChainHeadEvent, 16) c.chainHeadSub = c.blockSync.SubscribeChainHead(headCh) - c.engineClient = startEngineClient(c.chainConfig, c.engineRPC, headCh) + c.engineClient = startEngineClient(c.config, c.engineRPC, headCh) c.scheduler.Start() for _, url := range c.urls { diff --git a/beacon/blsync/config.go b/beacon/blsync/config.go deleted file mode 100644 index efc44b47d1..0000000000 --- a/beacon/blsync/config.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package blsync - -import ( - "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/urfave/cli/v2" -) - -// lightClientConfig contains beacon light client configuration -type lightClientConfig struct { - *types.ChainConfig - Checkpoint common.Hash -} - -var ( - MainnetConfig = lightClientConfig{ - ChainConfig: (&types.ChainConfig{ - GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"), - GenesisTime: 1606824023, - }). - AddFork("GENESIS", 0, []byte{0, 0, 0, 0}). - AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}). - AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}). - AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}). - AddFork("DENEB", 269568, []byte{4, 0, 0, 0}), - Checkpoint: common.HexToHash("0x388be41594ec7d6a6894f18c73f3469f07e2c19a803de4755d335817ed8e2e5a"), - } - - SepoliaConfig = lightClientConfig{ - ChainConfig: (&types.ChainConfig{ - GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"), - GenesisTime: 1655733600, - }). - AddFork("GENESIS", 0, []byte{144, 0, 0, 105}). - AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}). - AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}). - AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}). - AddFork("DENEB", 132608, []byte{144, 0, 0, 115}), - Checkpoint: common.HexToHash("0x1005a6d9175e96bfbce4d35b80f468e9bff0b674e1e861d16e09e10005a58e81"), - } -) - -func makeChainConfig(ctx *cli.Context) lightClientConfig { - var config lightClientConfig - customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name) - utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.BeaconConfigFlag) - switch { - case ctx.Bool(utils.MainnetFlag.Name): - config = MainnetConfig - case ctx.Bool(utils.SepoliaFlag.Name): - config = SepoliaConfig - default: - if !customConfig { - config = MainnetConfig - } - } - // Genesis root and time should always be specified together with custom chain config - if customConfig { - if !ctx.IsSet(utils.BeaconGenesisRootFlag.Name) { - utils.Fatalf("Custom beacon chain config is specified but genesis root is missing") - } - if !ctx.IsSet(utils.BeaconGenesisTimeFlag.Name) { - utils.Fatalf("Custom beacon chain config is specified but genesis time is missing") - } - if !ctx.IsSet(utils.BeaconCheckpointFlag.Name) { - utils.Fatalf("Custom beacon chain config is specified but checkpoint is missing") - } - config.ChainConfig = &types.ChainConfig{ - GenesisTime: ctx.Uint64(utils.BeaconGenesisTimeFlag.Name), - } - if c, err := hexutil.Decode(ctx.String(utils.BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 { - copy(config.GenesisValidatorsRoot[:len(c)], c) - } else { - utils.Fatalf("Invalid hex string", "beacon.genesis.gvroot", ctx.String(utils.BeaconGenesisRootFlag.Name), "error", err) - } - if err := config.ChainConfig.LoadForks(ctx.String(utils.BeaconConfigFlag.Name)); err != nil { - utils.Fatalf("Could not load beacon chain config file", "file name", ctx.String(utils.BeaconConfigFlag.Name), "error", err) - } - } else { - if ctx.IsSet(utils.BeaconGenesisRootFlag.Name) { - utils.Fatalf("Genesis root is specified but custom beacon chain config is missing") - } - if ctx.IsSet(utils.BeaconGenesisTimeFlag.Name) { - utils.Fatalf("Genesis time is specified but custom beacon chain config is missing") - } - } - // Checkpoint is required with custom chain config and is optional with pre-defined config - if ctx.IsSet(utils.BeaconCheckpointFlag.Name) { - if c, err := hexutil.Decode(ctx.String(utils.BeaconCheckpointFlag.Name)); err == nil && len(c) <= 32 { - copy(config.Checkpoint[:len(c)], c) - } else { - utils.Fatalf("Invalid hex string", "beacon.checkpoint", ctx.String(utils.BeaconCheckpointFlag.Name), "error", err) - } - } - return config -} diff --git a/beacon/blsync/engineclient.go b/beacon/blsync/engineclient.go index fb8f77f32b..c6569fdbde 100644 --- a/beacon/blsync/engineclient.go +++ b/beacon/blsync/engineclient.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ethereum/go-ethereum/beacon/engine" + "github.com/ethereum/go-ethereum/beacon/params" "github.com/ethereum/go-ethereum/beacon/types" "github.com/ethereum/go-ethereum/common" ctypes "github.com/ethereum/go-ethereum/core/types" @@ -31,14 +32,14 @@ import ( ) type engineClient struct { - config *lightClientConfig + config *params.ClientConfig rpc *rpc.Client rootCtx context.Context cancelRoot context.CancelFunc wg sync.WaitGroup } -func startEngineClient(config *lightClientConfig, rpc *rpc.Client, headCh <-chan types.ChainHeadEvent) *engineClient { +func startEngineClient(config *params.ClientConfig, rpc *rpc.Client, headCh <-chan types.ChainHeadEvent) *engineClient { ctx, cancel := context.WithCancel(context.Background()) ec := &engineClient{ config: config, diff --git a/beacon/light/committee_chain.go b/beacon/light/committee_chain.go index a8d032bb65..4fa87785c0 100644 --- a/beacon/light/committee_chain.go +++ b/beacon/light/committee_chain.go @@ -76,34 +76,32 @@ type CommitteeChain struct { unixNano func() int64 // system clock (simulated clock in tests) sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests) - config *types.ChainConfig - signerThreshold int + config *params.ChainConfig minimumUpdateScore types.UpdateScore enforceTime bool // enforceTime specifies whether the age of a signed header should be checked } // NewCommitteeChain creates a new CommitteeChain. -func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain { +func NewCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain { return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() }) } // NewTestCommitteeChain creates a new CommitteeChain for testing. -func NewTestCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, clock *mclock.Simulated) *CommitteeChain { +func NewTestCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool, clock *mclock.Simulated) *CommitteeChain { return newCommitteeChain(db, config, signerThreshold, enforceTime, dummyVerifier{}, clock, func() int64 { return int64(clock.Now()) }) } // newCommitteeChain creates a new CommitteeChain with the option of replacing the // clock source and signature verification for testing purposes. -func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain { +func newCommitteeChain(db ethdb.KeyValueStore, config *params.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain { s := &CommitteeChain{ - committeeCache: lru.NewCache[uint64, syncCommittee](10), - db: db, - sigVerifier: sigVerifier, - clock: clock, - unixNano: unixNano, - config: config, - signerThreshold: signerThreshold, - enforceTime: enforceTime, + committeeCache: lru.NewCache[uint64, syncCommittee](10), + db: db, + sigVerifier: sigVerifier, + clock: clock, + unixNano: unixNano, + config: config, + enforceTime: enforceTime, minimumUpdateScore: types.UpdateScore{ SignerCount: uint32(signerThreshold), SubPeriodIndex: params.SyncPeriodLength / 16, @@ -507,7 +505,7 @@ func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time if committee == nil { return false, age, nil } - if signingRoot, err := s.config.Forks.SigningRoot(head.Header); err == nil { + if signingRoot, err := s.config.Forks.SigningRoot(head.Header.Epoch(), head.Header.Hash()); err == nil { return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil } return false, age, nil diff --git a/beacon/light/committee_chain_test.go b/beacon/light/committee_chain_test.go index 57b6d7175c..17ba135905 100644 --- a/beacon/light/committee_chain_test.go +++ b/beacon/light/committee_chain_test.go @@ -31,15 +31,15 @@ var ( testGenesis = newTestGenesis() testGenesis2 = newTestGenesis() - tfBase = newTestForks(testGenesis, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, + tfBase = newTestForks(testGenesis, params.Forks{ + ¶ms.Fork{Epoch: 0, Version: []byte{0}}, }) - tfAlternative = newTestForks(testGenesis, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, - &types.Fork{Epoch: 0x700, Version: []byte{1}}, + tfAlternative = newTestForks(testGenesis, params.Forks{ + ¶ms.Fork{Epoch: 0, Version: []byte{0}}, + ¶ms.Fork{Epoch: 0x700, Version: []byte{1}}, }) - tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, + tfAnotherGenesis = newTestForks(testGenesis2, params.Forks{ + ¶ms.Fork{Epoch: 0, Version: []byte{0}}, }) tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false) @@ -226,13 +226,13 @@ type committeeChainTest struct { t *testing.T db *memorydb.Database clock *mclock.Simulated - config types.ChainConfig + config params.ChainConfig signerThreshold int enforceTime bool chain *CommitteeChain } -func newCommitteeChainTest(t *testing.T, config types.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest { +func newCommitteeChainTest(t *testing.T, config params.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest { c := &committeeChainTest{ t: t, db: memorydb.New(), @@ -298,20 +298,20 @@ func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint c.verifySignedHeader(tc, float64(end)+1.5, false) } -func newTestGenesis() types.ChainConfig { - var config types.ChainConfig +func newTestGenesis() params.ChainConfig { + var config params.ChainConfig rand.Read(config.GenesisValidatorsRoot[:]) return config } -func newTestForks(config types.ChainConfig, forks types.Forks) types.ChainConfig { +func newTestForks(config params.ChainConfig, forks params.Forks) params.ChainConfig { for _, fork := range forks { config.AddFork(fork.Name, fork.Epoch, fork.Version) } return config } -func newTestCommitteeChain(parent *testCommitteeChain, config types.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain { +func newTestCommitteeChain(parent *testCommitteeChain, config params.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain { tc := &testCommitteeChain{ config: config, } @@ -337,7 +337,7 @@ type testPeriod struct { type testCommitteeChain struct { periods []testPeriod - config types.ChainConfig + config params.ChainConfig } func (tc *testCommitteeChain) fillCommittees(begin, end int) { diff --git a/beacon/light/test_helpers.go b/beacon/light/test_helpers.go index f537d963a6..7bd19ca0ad 100644 --- a/beacon/light/test_helpers.go +++ b/beacon/light/test_helpers.go @@ -33,7 +33,7 @@ func GenerateTestCommittee() *types.SerializedSyncCommittee { return s } -func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate { +func GenerateTestUpdate(config *params.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate { update := new(types.LightClientUpdate) update.NextSyncCommitteeRoot = nextCommittee.Root() var attestedHeader types.Header @@ -48,9 +48,9 @@ func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nex return update } -func GenerateTestSignedHeader(header types.Header, config *types.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader { +func GenerateTestSignedHeader(header types.Header, config *params.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader { bitmask := makeBitmask(signerCount) - signingRoot, _ := config.Forks.SigningRoot(header) + signingRoot, _ := config.Forks.SigningRoot(header.Epoch(), header.Hash()) c, _ := dummyVerifier{}.deserializeSyncCommittee(committee) return types.SignedHeader{ Header: header, diff --git a/beacon/types/config.go b/beacon/params/config.go similarity index 94% rename from beacon/types/config.go rename to beacon/params/config.go index 7706e85f6c..be2a40f171 100644 --- a/beacon/types/config.go +++ b/beacon/params/config.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types +package params import ( "crypto/sha256" @@ -39,81 +39,13 @@ const syncCommitteeDomain = 7 var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"} -// Fork describes a single beacon chain fork and also stores the calculated -// signature domain used after this fork. -type Fork struct { - // Name of the fork in the chain config (config.yaml) file - Name string - - // Epoch when given fork version is activated - Epoch uint64 - - // Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types - Version []byte - - // index in list of known forks or MaxInt if unknown - knownIndex int - - // calculated by computeDomain, based on fork version and genesis validators root - domain merkle.Value -} - -// computeDomain returns the signature domain based on the given fork version -// and genesis validator set root. -func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) { - var ( - hasher = sha256.New() - forkVersion32 merkle.Value - forkDataRoot merkle.Value - ) - copy(forkVersion32[:], f.Version) - hasher.Write(forkVersion32[:]) - hasher.Write(genesisValidatorsRoot[:]) - hasher.Sum(forkDataRoot[:0]) - - f.domain[0] = syncCommitteeDomain - copy(f.domain[4:], forkDataRoot[:28]) -} - -// Forks is the list of all beacon chain forks in the chain configuration. -type Forks []*Fork - -// domain returns the signature domain for the given epoch (assumes that domains -// have already been calculated). -func (f Forks) domain(epoch uint64) (merkle.Value, error) { - for i := len(f) - 1; i >= 0; i-- { - if epoch >= f[i].Epoch { - return f[i].domain, nil - } - } - return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch) -} - -// SigningRoot calculates the signing root of the given header. -func (f Forks) SigningRoot(header Header) (common.Hash, error) { - domain, err := f.domain(header.Epoch()) - if err != nil { - return common.Hash{}, err - } - var ( - signingRoot common.Hash - headerHash = header.Hash() - hasher = sha256.New() - ) - hasher.Write(headerHash[:]) - hasher.Write(domain[:]) - hasher.Sum(signingRoot[:0]) - - return signingRoot, nil -} - -func (f Forks) Len() int { return len(f) } -func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] } -func (f Forks) Less(i, j int) bool { - if f[i].Epoch != f[j].Epoch { - return f[i].Epoch < f[j].Epoch - } - return f[i].knownIndex < f[j].knownIndex +// ClientConfig contains beacon light client configuration. +type ClientConfig struct { + ChainConfig + Apis []string + CustomHeader map[string]string + Threshold int + NoFilter bool } // ChainConfig contains the beacon chain configuration. @@ -121,6 +53,7 @@ type ChainConfig struct { GenesisTime uint64 // Unix timestamp of slot 0 GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation Forks Forks + Checkpoint common.Hash } // ForkAtEpoch returns the latest active fork at the given epoch. @@ -202,3 +135,79 @@ func (c *ChainConfig) LoadForks(path string) error { } return nil } + +// Fork describes a single beacon chain fork and also stores the calculated +// signature domain used after this fork. +type Fork struct { + // Name of the fork in the chain config (config.yaml) file + Name string + + // Epoch when given fork version is activated + Epoch uint64 + + // Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types + Version []byte + + // index in list of known forks or MaxInt if unknown + knownIndex int + + // calculated by computeDomain, based on fork version and genesis validators root + domain merkle.Value +} + +// computeDomain returns the signature domain based on the given fork version +// and genesis validator set root. +func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) { + var ( + hasher = sha256.New() + forkVersion32 merkle.Value + forkDataRoot merkle.Value + ) + copy(forkVersion32[:], f.Version) + hasher.Write(forkVersion32[:]) + hasher.Write(genesisValidatorsRoot[:]) + hasher.Sum(forkDataRoot[:0]) + + f.domain[0] = syncCommitteeDomain + copy(f.domain[4:], forkDataRoot[:28]) +} + +// Forks is the list of all beacon chain forks in the chain configuration. +type Forks []*Fork + +// domain returns the signature domain for the given epoch (assumes that domains +// have already been calculated). +func (f Forks) domain(epoch uint64) (merkle.Value, error) { + for i := len(f) - 1; i >= 0; i-- { + if epoch >= f[i].Epoch { + return f[i].domain, nil + } + } + return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch) +} + +// SigningRoot calculates the signing root of the given header. +func (f Forks) SigningRoot(epoch uint64, root common.Hash) (common.Hash, error) { + domain, err := f.domain(epoch) + if err != nil { + return common.Hash{}, err + } + var ( + signingRoot common.Hash + hasher = sha256.New() + ) + hasher.Write(root[:]) + hasher.Write(domain[:]) + hasher.Sum(signingRoot[:0]) + + return signingRoot, nil +} + +func (f Forks) Len() int { return len(f) } +func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] } +func (f Forks) Less(i, j int) bool { + if f[i].Epoch != f[j].Epoch { + return f[i].Epoch < f[j].Epoch + } + return f[i].knownIndex < f[j].knownIndex +} diff --git a/beacon/params/networks.go b/beacon/params/networks.go new file mode 100644 index 0000000000..5b00b27953 --- /dev/null +++ b/beacon/params/networks.go @@ -0,0 +1,56 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import ( + "github.com/ethereum/go-ethereum/common" +) + +var ( + MainnetLightConfig = (&ChainConfig{ + GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"), + GenesisTime: 1606824023, + Checkpoint: common.HexToHash("0x6509b691f4de4f7b083f2784938fd52f0e131675432b3fd85ea549af9aebd3d0"), + }). + AddFork("GENESIS", 0, []byte{0, 0, 0, 0}). + AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}). + AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}). + AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}). + AddFork("DENEB", 269568, []byte{4, 0, 0, 0}) + + SepoliaLightConfig = (&ChainConfig{ + GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"), + GenesisTime: 1655733600, + Checkpoint: common.HexToHash("0x456e85f5608afab3465a0580bff8572255f6d97af0c5f939e3f7536b5edb2d3f"), + }). + AddFork("GENESIS", 0, []byte{144, 0, 0, 105}). + AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}). + AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}). + AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}). + AddFork("DENEB", 132608, []byte{144, 0, 0, 115}) + + HoleskyLightConfig = (&ChainConfig{ + GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"), + GenesisTime: 1695902400, + Checkpoint: common.HexToHash("0x6456a1317f54d4b4f2cb5bc9d153b5af0988fe767ef0609f0236cf29030bcff7"), + }). + AddFork("GENESIS", 0, []byte{1, 1, 112, 0}). + AddFork("ALTAIR", 0, []byte{2, 1, 112, 0}). + AddFork("BELLATRIX", 0, []byte{3, 1, 112, 0}). + AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}). + AddFork("DENEB", 29696, []byte{5, 1, 112, 0}) +) diff --git a/build/ci.go b/build/ci.go index 1765d750c2..754d88a86a 100644 --- a/build/ci.go +++ b/build/ci.go @@ -24,9 +24,14 @@ Usage: go run build/ci.go Available commands are: - install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables - test [ -coverage ] [ packages... ] -- runs the tests - lint -- runs certain pre-selected linters + lint -- runs certain pre-selected linters + check_tidy -- verifies that everything is 'go mod tidy'-ed + check_generate -- verifies that everything is 'go generate'-ed + check_baddeps -- verifies that certain dependencies are avoided + + install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables + test [ -coverage ] [ packages... ] -- runs the tests + archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts importkeys -- imports signing keys from env debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package @@ -39,17 +44,16 @@ package main import ( "bytes" - "crypto/sha256" "encoding/base64" "flag" "fmt" - "io" "log" "os" "os/exec" "path" "path/filepath" "runtime" + "slices" "strings" "time" @@ -156,6 +160,12 @@ func main() { doTest(os.Args[2:]) case "lint": doLint(os.Args[2:]) + case "check_tidy": + doCheckTidy() + case "check_generate": + doCheckGenerate() + case "check_baddeps": + doCheckBadDeps() case "archive": doArchive(os.Args[2:]) case "dockerx": @@ -168,8 +178,6 @@ func main() { doPurge(os.Args[2:]) case "sanitycheck": doSanityCheck() - case "generate": - doGenerate() default: log.Fatal("unknown command ", os.Args[1]) } @@ -219,8 +227,7 @@ func doInstall(cmdline []string) { // Do the build! for _, pkg := range packages { - args := make([]string, len(gobuild.Args)) - copy(args, gobuild.Args) + args := slices.Clone(gobuild.Args) args = append(args, "-o", executablePath(path.Base(pkg))) args = append(args, pkg) build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env}) @@ -348,128 +355,93 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string { return filepath.Join(cachedir, base) } -// hashAllSourceFiles iterates all files under the top-level project directory -// computing the hash of each file (excluding files within the tests -// subrepo) -func hashAllSourceFiles() (map[string][32]byte, error) { - res := make(map[string][32]byte) - err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error { - if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) { - return filepath.SkipDir - } - if !d.Type().IsRegular() { - return nil - } - // open the file and hash it - f, err := os.OpenFile(path, os.O_RDONLY, 0666) - if err != nil { - return err - } - hasher := sha256.New() - if _, err := io.Copy(hasher, f); err != nil { - return err - } - res[path] = [32]byte(hasher.Sum(nil)) - return nil - }) +// doCheckTidy assets that the Go modules files are tidied already. +func doCheckTidy() { + targets := []string{"go.mod", "go.sum"} + + hashes, err := build.HashFiles(targets) if err != nil { - return nil, err + log.Fatalf("failed to hash go.mod/go.sum: %v", err) } - return res, nil -} + build.MustRun(new(build.GoToolchain).Go("mod", "tidy")) -// hashSourceFiles iterates the provided set of filepaths (relative to the top-level geth project directory) -// computing the hash of each file. -func hashSourceFiles(files []string) (map[string][32]byte, error) { - res := make(map[string][32]byte) - for _, filePath := range files { - f, err := os.OpenFile(filePath, os.O_RDONLY, 0666) - if err != nil { - return nil, err - } - hasher := sha256.New() - if _, err := io.Copy(hasher, f); err != nil { - return nil, err - } - res[filePath] = [32]byte(hasher.Sum(nil)) - } - return res, nil -} - -// compareHashedFilesets compares two maps (key is relative file path to top-level geth directory, value is its hash) -// and returns the list of file paths whose hashes differed. -func compareHashedFilesets(preHashes map[string][32]byte, postHashes map[string][32]byte) []string { - updates := []string{} - for path, postHash := range postHashes { - preHash, ok := preHashes[path] - if !ok || preHash != postHash { - updates = append(updates, path) - } - } - return updates -} - -func doGoModTidy() { - targetFiles := []string{"go.mod", "go.sum"} - preHashes, err := hashSourceFiles(targetFiles) + tidied, err := build.HashFiles(targets) if err != nil { - log.Fatal("failed to hash go.mod/go.sum", "err", err) + log.Fatalf("failed to rehash go.mod/go.sum: %v", err) } - tc := new(build.GoToolchain) - c := tc.Go("mod", "tidy") - build.MustRun(c) - postHashes, err := hashSourceFiles(targetFiles) - updates := compareHashedFilesets(preHashes, postHashes) - for _, updatedFile := range updates { - fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile) - } - if len(updates) != 0 { - log.Fatal("go.sum and/or go.mod were updated by running 'go mod tidy'") + if updates := build.DiffHashes(hashes, tidied); len(updates) > 0 { + log.Fatalf("files changed on running 'go mod tidy': %v", updates) } + fmt.Println("No untidy module files detected.") } -// doGenerate ensures that re-generating generated files does not cause -// any mutations in the source file tree: i.e. all generated files were -// updated and committed. Any stale generated files are updated. -func doGenerate() { +// doCheckGenerate ensures that re-generating generated files does not cause +// any mutations in the source file tree. +func doCheckGenerate() { var ( - tc = new(build.GoToolchain) cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.") - verify = flag.Bool("verify", false, "check whether any files are changed by go generate") ) + // Compute the origin hashes of all the files + var hashes map[string][32]byte - protocPath := downloadProtoc(*cachedir) - protocGenGoPath := downloadProtocGenGo(*cachedir) - - var preHashes map[string][32]byte - if *verify { - var err error - preHashes, err = hashAllSourceFiles() - if err != nil { - log.Fatal("failed to compute map of source hashes", "err", err) - } + var err error + hashes, err = build.HashFolder(".", []string{"tests/testdata", "build/cache"}) + if err != nil { + log.Fatal("Error computing hashes", "err", err) } - - c := tc.Go("generate", "./...") + // Run any go generate steps we might be missing + var ( + protocPath = downloadProtoc(*cachedir) + protocGenGoPath = downloadProtocGenGo(*cachedir) + ) + c := new(build.GoToolchain).Go("generate", "./...") pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")} c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator))) build.MustRun(c) - if !*verify { - return - } - // Check if files were changed. - postHashes, err := hashAllSourceFiles() + // Check if generate file hashes have changed + generated, err := build.HashFolder(".", []string{"tests/testdata", "build/cache"}) if err != nil { - log.Fatal("error computing source tree file hashes", "err", err) + log.Fatalf("Error re-computing hashes: %v", err) } - updates := compareHashedFilesets(preHashes, postHashes) - for _, updatedFile := range updates { - fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile) + updates := build.DiffHashes(hashes, generated) + for _, file := range updates { + log.Printf("File changed: %s", file) } if len(updates) != 0 { log.Fatal("One or more generated files were updated by running 'go generate ./...'") } + fmt.Println("No stale files detected.") +} + +// doCheckBadDeps verifies whether certain unintended dependencies between some +// packages leak into the codebase due to a refactor. This is not an exhaustive +// list, rather something we build up over time at sensitive places. +func doCheckBadDeps() { + baddeps := [][2]string{ + // Rawdb tends to be a dumping ground for db utils, sometimes leaking the db itself + {"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/leveldb"}, + {"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/pebbledb"}, + } + tc := new(build.GoToolchain) + + var failed bool + for _, rule := range baddeps { + out, err := tc.Go("list", "-deps", rule[0]).CombinedOutput() + if err != nil { + log.Fatalf("Failed to list '%s' dependencies: %v", rule[0], err) + } + for _, line := range strings.Split(string(out), "\n") { + if strings.TrimSpace(line) == rule[1] { + log.Printf("Found bad dependency '%s' -> '%s'", rule[0], rule[1]) + failed = true + } + } + } + if failed { + log.Fatalf("Bad dependencies detected.") + } + fmt.Println("No bad dependencies detected.") } // doLint runs golangci-lint on requested packages. @@ -486,8 +458,6 @@ func doLint(cmdline []string) { linter := downloadLinter(*cachedir) lflags := []string{"run", "--config", ".golangci.yml"} build.MustRunCommandWithOutput(linter, append(lflags, packages...)...) - - doGoModTidy() fmt.Println("You have achieved perfection.") } diff --git a/cmd/blsync/main.go b/cmd/blsync/main.go index f9b8575edf..d74e1496cd 100644 --- a/cmd/blsync/main.go +++ b/cmd/blsync/main.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "slices" "github.com/ethereum/go-ethereum/beacon/blsync" "github.com/ethereum/go-ethereum/cmd/utils" @@ -33,7 +34,7 @@ import ( func main() { app := flags.NewApp("beacon light syncer tool") - app.Flags = flags.Merge([]cli.Flag{ + app.Flags = slices.Concat([]cli.Flag{ utils.BeaconApiFlag, utils.BeaconApiHeaderFlag, utils.BeaconThresholdFlag, @@ -45,6 +46,7 @@ func main() { //TODO datadir for optional permanent database utils.MainnetFlag, utils.SepoliaFlag, + utils.HoleskyFlag, utils.BlsyncApiFlag, utils.BlsyncJWTSecretFlag, }, @@ -68,7 +70,7 @@ func main() { func sync(ctx *cli.Context) error { // set up blsync - client := blsync.NewClient(ctx) + client := blsync.NewClient(utils.MakeBeaconLightConfig(ctx)) client.SetEngineRPC(makeRPCClient(ctx)) client.Start() diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go index 3b5400ca3a..8c48b3a557 100644 --- a/cmd/devp2p/discv4cmd.go +++ b/cmd/devp2p/discv4cmd.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "slices" "strconv" "strings" "time" @@ -28,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" @@ -83,7 +83,7 @@ var ( Name: "listen", Usage: "Runs a discovery node", Action: discv4Listen, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{ + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{ httpAddrFlag, }), } @@ -91,7 +91,7 @@ var ( Name: "crawl", Usage: "Updates a nodes.json file with random nodes found in the DHT", Action: discv4Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), } discv4TestCommand = &cli.Command{ Name: "test", diff --git a/cmd/devp2p/discv5cmd.go b/cmd/devp2p/discv5cmd.go index 0dac945269..2422ef6644 100644 --- a/cmd/devp2p/discv5cmd.go +++ b/cmd/devp2p/discv5cmd.go @@ -19,11 +19,11 @@ package main import ( "errors" "fmt" + "slices" "time" "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/urfave/cli/v2" ) @@ -56,7 +56,7 @@ var ( Name: "crawl", Usage: "Updates a nodes.json file with random nodes found in the DHT", Action: discv5Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{ + Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{ crawlTimeoutFlag, }), } diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 994684ab22..0d4471b8d5 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -21,6 +21,7 @@ import ( "fmt" "math/big" "os" + "slices" "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" "github.com/ethereum/go-ethereum/internal/debug" @@ -254,7 +255,7 @@ var traceFlags = []cli.Flag{ var app = flags.NewApp("the evm command line interface") func init() { - app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags) + app.Flags = slices.Concat(vmFlags, traceFlags, debug.Flags) app.Commands = []*cli.Command{ compileCommand, disasmCommand, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 235fed6630..8c382e6257 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -24,6 +24,7 @@ import ( "math/big" "os" goruntime "runtime" + "slices" "testing" "time" @@ -50,7 +51,7 @@ var runCommand = &cli.Command{ Usage: "Run arbitrary evm binary", ArgsUsage: "", Description: `The run command runs arbitrary EVM code.`, - Flags: flags.Merge(vmFlags, traceFlags), + Flags: slices.Concat(vmFlags, traceFlags), } // readGenesis will read the given JSON format genesis file and return @@ -75,36 +76,53 @@ func readGenesis(genesisPath string) *core.Genesis { } type execStats struct { - time time.Duration // The execution time. - allocs int64 // The number of heap allocations during execution. - bytesAllocated int64 // The cumulative number of bytes allocated during execution. + Time time.Duration `json:"time"` // The execution Time. + Allocs int64 `json:"allocs"` // The number of heap allocations during execution. + BytesAllocated int64 `json:"bytesAllocated"` // The cumulative number of bytes allocated during execution. + GasUsed uint64 `json:"gasUsed"` // the amount of gas used during execution } -func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []byte, gasLeft uint64, stats execStats, err error) { +func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, execStats, error) { if bench { + // Do one warm-up run + output, gasUsed, err := execFunc() result := testing.Benchmark(func(b *testing.B) { for i := 0; i < b.N; i++ { - output, gasLeft, err = execFunc() + haveOutput, haveGasUsed, haveErr := execFunc() + if !bytes.Equal(haveOutput, output) { + b.Fatalf("output differs, have\n%x\nwant%x\n", haveOutput, output) + } + if haveGasUsed != gasUsed { + b.Fatalf("gas differs, have %v want%v", haveGasUsed, gasUsed) + } + if haveErr != err { + b.Fatalf("err differs, have %v want%v", haveErr, err) + } } }) - // Get the average execution time from the benchmarking result. // There are other useful stats here that could be reported. - stats.time = time.Duration(result.NsPerOp()) - stats.allocs = result.AllocsPerOp() - stats.bytesAllocated = result.AllocedBytesPerOp() - } else { - var memStatsBefore, memStatsAfter goruntime.MemStats - goruntime.ReadMemStats(&memStatsBefore) - startTime := time.Now() - output, gasLeft, err = execFunc() - stats.time = time.Since(startTime) - goruntime.ReadMemStats(&memStatsAfter) - stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs) - stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc) + stats := execStats{ + Time: time.Duration(result.NsPerOp()), + Allocs: result.AllocsPerOp(), + BytesAllocated: result.AllocedBytesPerOp(), + GasUsed: gasUsed, + } + return output, stats, err } - - return output, gasLeft, stats, err + var memStatsBefore, memStatsAfter goruntime.MemStats + goruntime.ReadMemStats(&memStatsBefore) + t0 := time.Now() + output, gasUsed, err := execFunc() + duration := time.Since(t0) + goruntime.ReadMemStats(&memStatsAfter) + stats := execStats{ + Time: duration, + Allocs: int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs), + BytesAllocated: int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc), + GasUsed: gasUsed, + } + return output, stats, err } func runCmd(ctx *cli.Context) error { @@ -264,12 +282,13 @@ func runCmd(ctx *cli.Context) error { statedb.SetCode(receiver, code) } execFunc = func() ([]byte, uint64, error) { - return runtime.Call(receiver, input, &runtimeConfig) + output, gasLeft, err := runtime.Call(receiver, input, &runtimeConfig) + return output, initialGas - gasLeft, err } } bench := ctx.Bool(BenchFlag.Name) - output, leftOverGas, stats, err := timedExec(bench, execFunc) + output, stats, err := timedExec(bench, execFunc) if ctx.Bool(DumpFlag.Name) { root, err := statedb.Commit(genesisConfig.Number, true) @@ -299,7 +318,7 @@ func runCmd(ctx *cli.Context) error { execution time: %v allocations: %d allocated bytes: %d -`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated) +`, stats.GasUsed, stats.Time, stats.Allocs, stats.BytesAllocated) } if tracer == nil { fmt.Printf("%#x\n", output) diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index 4514367e8a..d0a0d3287c 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -27,26 +27,51 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/tests" "github.com/urfave/cli/v2" ) +var ( + forkFlag = &cli.StringFlag{ + Name: "statetest.fork", + Usage: "The hard-fork to run the test against", + Category: flags.VMCategory, + } + idxFlag = &cli.IntFlag{ + Name: "statetest.index", + Usage: "The index of the subtest to run", + Category: flags.VMCategory, + Value: -1, // default to select all subtest indices + } + testNameFlag = &cli.StringFlag{ + Name: "statetest.name", + Usage: "The name of the state test to run", + Category: flags.VMCategory, + } +) var stateTestCommand = &cli.Command{ Action: stateTestCmd, Name: "statetest", Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).", ArgsUsage: "", + Flags: []cli.Flag{ + forkFlag, + idxFlag, + testNameFlag, + }, } // StatetestResult contains the execution status after running a state test, any // error that might have occurred and a dump of the final state if requested. type StatetestResult struct { - Name string `json:"name"` - Pass bool `json:"pass"` - Root *common.Hash `json:"stateRoot,omitempty"` - Fork string `json:"fork"` - Error string `json:"error,omitempty"` - State *state.Dump `json:"state,omitempty"` + Name string `json:"name"` + Pass bool `json:"pass"` + Root *common.Hash `json:"stateRoot,omitempty"` + Fork string `json:"fork"` + Error string `json:"error,omitempty"` + State *state.Dump `json:"state,omitempty"` + BenchStats *execStats `json:"benchStats,omitempty"` } func stateTestCmd(ctx *cli.Context) error { @@ -67,7 +92,7 @@ func stateTestCmd(ctx *cli.Context) error { } // Load the test content from the input file if len(ctx.Args().First()) != 0 { - return runStateTest(ctx.Args().First(), cfg, ctx.Bool(DumpFlag.Name)) + return runStateTest(ctx, ctx.Args().First(), cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name)) } // Read filenames from stdin and execute back-to-back scanner := bufio.NewScanner(os.Stdin) @@ -76,15 +101,48 @@ func stateTestCmd(ctx *cli.Context) error { if len(fname) == 0 { return nil } - if err := runStateTest(fname, cfg, ctx.Bool(DumpFlag.Name)); err != nil { + if err := runStateTest(ctx, fname, cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name)); err != nil { return err } } return nil } +type stateTestCase struct { + name string + test tests.StateTest + st tests.StateSubtest +} + +// collectMatchedSubtests returns test cases which match against provided filtering CLI parameters +func collectMatchedSubtests(ctx *cli.Context, testsByName map[string]tests.StateTest) []stateTestCase { + var res []stateTestCase + subtestName := ctx.String(testNameFlag.Name) + if subtestName != "" { + if subtest, ok := testsByName[subtestName]; ok { + testsByName := make(map[string]tests.StateTest) + testsByName[subtestName] = subtest + } + } + idx := ctx.Int(idxFlag.Name) + fork := ctx.String(forkFlag.Name) + + for key, test := range testsByName { + for _, st := range test.Subtests() { + if idx != -1 && st.Index != idx { + continue + } + if fork != "" && st.Fork != fork { + continue + } + res = append(res, stateTestCase{name: key, st: st, test: test}) + } + } + return res +} + // runStateTest loads the state-test given by fname, and executes the test. -func runStateTest(fname string, cfg vm.Config, dump bool) error { +func runStateTest(ctx *cli.Context, fname string, cfg vm.Config, dump bool, bench bool) error { src, err := os.ReadFile(fname) if err != nil { return err @@ -94,31 +152,38 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error { return err } + matchingTests := collectMatchedSubtests(ctx, testsByName) + // Iterate over all the tests, run them and aggregate the results - results := make([]StatetestResult, 0, len(testsByName)) - for key, test := range testsByName { - for _, st := range test.Subtests() { - // Run the test and aggregate the result - result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} - test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) { - var root common.Hash - if tstate.StateDB != nil { - root = tstate.StateDB.IntermediateRoot(false) - result.Root = &root - fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) - if dump { // Dump any state to aid debugging - cpy, _ := state.New(root, tstate.StateDB.Database()) - dump := cpy.RawDump(nil) - result.State = &dump - } - } - if err != nil { - // Test failed, mark as so - result.Pass, result.Error = false, err.Error() + var results []StatetestResult + for _, test := range matchingTests { + // Run the test and aggregate the result + result := &StatetestResult{Name: test.name, Fork: test.st.Fork, Pass: true} + test.test.Run(test.st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) { + var root common.Hash + if tstate.StateDB != nil { + root = tstate.StateDB.IntermediateRoot(false) + result.Root = &root + fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) + if dump { // Dump any state to aid debugging + cpy, _ := state.New(root, tstate.StateDB.Database()) + dump := cpy.RawDump(nil) + result.State = &dump } + } + if err != nil { + // Test failed, mark as so + result.Pass, result.Error = false, err.Error() + } + }) + if bench { + _, stats, _ := timedExec(true, func() ([]byte, uint64, error) { + _, _, gasUsed, _ := test.test.RunNoVerify(test.st, cfg, false, rawdb.HashScheme) + return nil, gasUsed, nil }) - results = append(results, *result) + result.BenchStats = &stats } + results = append(results, *result) } out, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(out)) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index d85e4a83c8..f6dc1cf4bf 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "runtime" + "slices" "strconv" "sync/atomic" "time" @@ -36,7 +37,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" @@ -49,7 +49,7 @@ var ( Name: "init", Usage: "Bootstrap and initialize a new genesis block", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CachePreimagesFlag, utils.OverrideCancun, utils.OverrideVerkle, @@ -76,7 +76,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`, Name: "import", Usage: "Import a blockchain file", ArgsUsage: " ( ... ) ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, utils.GCModeFlag, @@ -115,7 +115,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`, Name: "export", Usage: "Export blockchain into file", ArgsUsage: " [ ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, }, utils.DatabaseFlags), @@ -131,7 +131,7 @@ be gzipped.`, Name: "import-history", Usage: "Import an Era archive", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.TxLookupLimitFlag, }, utils.DatabaseFlags, @@ -147,7 +147,7 @@ from Era archives. Name: "export-history", Usage: "Export blockchain history to Era archives", ArgsUsage: " ", - Flags: flags.Merge(utils.DatabaseFlags), + Flags: slices.Concat(utils.DatabaseFlags), Description: ` The export-history command will export blocks and their corresponding receipts into Era archives. Eras are typically packaged in steps of 8192 blocks. @@ -158,7 +158,7 @@ into Era archives. Eras are typically packaged in steps of 8192 blocks. Name: "import-preimages", Usage: "Import the preimage database from an RLP stream", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, }, utils.DatabaseFlags), @@ -173,7 +173,7 @@ It's deprecated, please use "geth db import" instead. Name: "dump", Usage: "Dump a specific block from storage", ArgsUsage: "[? | ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.CacheFlag, utils.IterativeOutputFlag, utils.ExcludeCodeFlag, diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 8282c80c41..17ed9fb606 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -23,6 +23,7 @@ import ( "os" "reflect" "runtime" + "slices" "strings" "unicode" @@ -53,7 +54,7 @@ var ( Name: "dumpconfig", Usage: "Export configuration values in a TOML format", ArgsUsage: "", - Flags: flags.Merge(nodeFlags, rpcFlags), + Flags: slices.Concat(nodeFlags, rpcFlags), Description: `Export configuration values in TOML format (to stdout by default).`, } @@ -132,7 +133,7 @@ func defaultNodeConfig() node.Config { cfg.Version = version.WithCommit(git.Commit, git.Date) cfg.HTTPModules = append(cfg.HTTPModules, "eth") cfg.WSModules = append(cfg.WSModules, "eth") - cfg.IPCPath = "geth.ipc" + cfg.IPCPath = clientIdentifier + ".ipc" return cfg } @@ -239,7 +240,7 @@ func makeFullNode(ctx *cli.Context) *node.Node { // Start blsync mode. srv := rpc.NewServer() srv.RegisterName("engine", catalyst.NewConsensusAPI(eth)) - blsyncer := blsync.NewClient(ctx) + blsyncer := blsync.NewClient(utils.MakeBeaconLightConfig(ctx)) blsyncer.SetEngineRPC(rpc.DialInProc(srv)) stack.RegisterLifecycle(blsyncer) } else { diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go index 2a59f0052f..bf38c86349 100644 --- a/cmd/geth/consolecmd.go +++ b/cmd/geth/consolecmd.go @@ -18,11 +18,11 @@ package main import ( "fmt" + "slices" "strings" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/console" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/urfave/cli/v2" ) @@ -33,7 +33,7 @@ var ( Action: localConsole, Name: "console", Usage: "Start an interactive JavaScript environment", - Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags), + Flags: slices.Concat(nodeFlags, rpcFlags, consoleFlags), Description: ` The Geth console is an interactive shell for the JavaScript runtime environment which exposes a node admin interface as well as the Ðapp JavaScript API. @@ -45,7 +45,7 @@ See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`, Name: "attach", Usage: "Start an interactive JavaScript environment (connect to node)", ArgsUsage: "[endpoint]", - Flags: flags.Merge([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags), + Flags: slices.Concat([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags), Description: ` The Geth console is an interactive shell for the JavaScript runtime environment which exposes a node admin interface as well as the Ðapp JavaScript API. @@ -58,7 +58,7 @@ This command allows to open a console on a running geth node.`, Name: "js", Usage: "(DEPRECATED) Execute the specified JavaScript files", ArgsUsage: " [jsfile...]", - Flags: flags.Merge(nodeFlags, consoleFlags), + Flags: slices.Concat(nodeFlags, consoleFlags), Description: ` The JavaScript VM exposes a node admin interface as well as the Ðapp JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`, diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 052ae0eab2..7622246050 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -22,6 +22,7 @@ import ( "os" "os/signal" "path/filepath" + "slices" "strconv" "strings" "syscall" @@ -36,7 +37,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -60,7 +60,7 @@ var ( Name: "removedb", Usage: "Remove blockchain and state databases", ArgsUsage: "", - Flags: flags.Merge(utils.DatabaseFlags, + Flags: slices.Concat(utils.DatabaseFlags, []cli.Flag{removeStateDataFlag, removeChainDataFlag}), Description: ` Remove blockchain and state databases`, @@ -89,7 +89,7 @@ Remove blockchain and state databases`, Action: inspect, Name: "inspect", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Usage: "Inspect the storage size for each type of data in the database", @@ -99,7 +99,7 @@ Remove blockchain and state databases`, Action: checkStateContent, Name: "check-state-content", ArgsUsage: "", - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Usage: "Verify that state data is cryptographically correct", Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes. For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates @@ -109,7 +109,7 @@ a data corruption.`, Action: dbStats, Name: "stats", Usage: "Print leveldb statistics", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), } @@ -117,7 +117,7 @@ a data corruption.`, Action: dbCompact, Name: "compact", Usage: "Compact leveldb database. WARNING: May take a very long time", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, utils.CacheFlag, utils.CacheDatabaseFlag, @@ -131,7 +131,7 @@ corruption if it is aborted during execution'!`, Name: "get", Usage: "Show the value of a database key", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", @@ -141,7 +141,7 @@ corruption if it is aborted during execution'!`, Name: "delete", Usage: "Delete a database key (WARNING: may corrupt your database)", ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command deletes the specified database key from the database. @@ -152,7 +152,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "put", Usage: "Set the value of a database key (WARNING: may corrupt your database)", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command sets a given database key to the given value. @@ -163,7 +163,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "dumptrie", Usage: "Show the storage key/values of a given storage trie", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", @@ -173,7 +173,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "freezer-index", Usage: "Dump out the index of a specific freezer table", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command displays information about the freezer index.", @@ -183,7 +183,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "import", Usage: "Imports leveldb-data from an exported RLP dump.", ArgsUsage: " has .gz suffix, gzip compression will be used.", ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", @@ -202,7 +202,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Action: showMetaData, Name: "metadata", Usage: "Shows metadata about the chain status.", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Shows metadata about the chain status.", @@ -212,7 +212,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, Name: "inspect-history", Usage: "Inspect the state history within block range", ArgsUsage: "
[OPTIONAL ]", - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.SyncModeFlag, &cli.Uint64Flag{ Name: "start", diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 2675a61675..10d4052737 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -20,6 +20,7 @@ package main import ( "fmt" "os" + "slices" "sort" "strconv" "strings" @@ -53,7 +54,7 @@ const ( var ( // flags that configure the node - nodeFlags = flags.Merge([]cli.Flag{ + nodeFlags = slices.Concat([]cli.Flag{ utils.IdentityFlag, utils.UnlockedAccountFlag, utils.PasswordFileFlag, @@ -66,7 +67,7 @@ var ( utils.SmartCardDaemonPathFlag, utils.OverrideCancun, utils.OverrideVerkle, - utils.EnablePersonal, + utils.EnablePersonal, // deprecated utils.TxPoolLocalsFlag, utils.TxPoolNoLocalsFlag, utils.TxPoolJournalFlag, @@ -251,7 +252,7 @@ func init() { } sort.Sort(cli.CommandsByName(app.Commands)) - app.Flags = flags.Merge( + app.Flags = slices.Concat( nodeFlags, rpcFlags, consoleFlags, diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 14c6826e1d..f0be52a0df 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "os" + "slices" "time" "github.com/ethereum/go-ethereum/cmd/utils" @@ -32,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -50,7 +50,7 @@ var ( Usage: "Prune stale ethereum state data based on the snapshot", ArgsUsage: "", Action: pruneState, - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.BloomFilterSizeFlag, }, utils.NetworkFlags, utils.DatabaseFlags), Description: ` @@ -70,7 +70,7 @@ WARNING: it's only supported in hash mode(--state.scheme=hash)". Usage: "Recalculate state hash based on the snapshot for verification", ArgsUsage: "", Action: verifyState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot verify-state will traverse the whole accounts and storages set based on the specified @@ -83,7 +83,7 @@ In other words, this command does the snapshot to trie conversion. Usage: "Check that there is no 'dangling' snap storage", ArgsUsage: "", Action: checkDanglingStorage, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot check-dangling-storage traverses the snap storage data, and verifies that all snapshot storage data has a corresponding account. @@ -94,7 +94,7 @@ data, and verifies that all snapshot storage data has a corresponding account. Usage: "Check all snapshot layers for the specific account", ArgsUsage: "
", Action: checkAccount, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot inspect-account
checks all snapshot layers and prints out information about the specified address. @@ -105,7 +105,7 @@ information about the specified address. Usage: "Traverse the state with given root hash and perform quick verification", ArgsUsage: "", Action: traverseState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-state will traverse the whole state from the given state root and will abort if any @@ -120,7 +120,7 @@ It's also usable without snapshot enabled. Usage: "Traverse the state with given root hash and perform detailed verification", ArgsUsage: "", Action: traverseRawState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-rawstate will traverse the whole state from the given root and will abort if any referenced @@ -136,7 +136,7 @@ It's also usable without snapshot enabled. Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)", ArgsUsage: "[? | ]", Action: dumpState, - Flags: flags.Merge([]cli.Flag{ + Flags: slices.Concat([]cli.Flag{ utils.ExcludeCodeFlag, utils.ExcludeStorageFlag, utils.StartKeyFlag, diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 9eb37fb5a8..6490f832af 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -22,11 +22,11 @@ import ( "errors" "fmt" "os" + "slices" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-verkle" "github.com/urfave/cli/v2" @@ -45,7 +45,7 @@ var ( Usage: "verify the conversion of a MPT into a verkle tree", ArgsUsage: "", Action: verifyVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle verify This command takes a root commitment and attempts to rebuild the tree. @@ -56,7 +56,7 @@ This command takes a root commitment and attempts to rebuild the tree. Usage: "Dump a verkle tree to a DOT file", ArgsUsage: " [ ...]", Action: expandVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), + Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle dump [ ...] This command will produce a dot file representing the tree, rooted at . diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e98d5cc8e3..4eef66ebc6 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -40,6 +40,7 @@ import ( bparams "github.com/ethereum/go-ethereum/beacon/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool/blobpool" @@ -176,12 +177,6 @@ var ( Usage: "Custom node name", Category: flags.NetworkingCategory, } - DocRootFlag = &flags.DirectoryFlag{ - Name: "docroot", - Usage: "Document Root for HTTPClient file scheme", - Value: flags.DirectoryString(flags.HomeDir()), - Category: flags.APICategory, - } ExitWhenSyncedFlag = &cli.BoolFlag{ Name: "exitwhensynced", Usage: "Exits after block synchronisation completes", @@ -217,8 +212,7 @@ var ( Value: 0, } - defaultSyncMode = ethconfig.Defaults.SyncMode - SnapshotFlag = &cli.BoolFlag{ + SnapshotFlag = &cli.BoolFlag{ Name: "snapshot", Usage: `Enables snapshot-database mode (default = enable)`, Value: true, @@ -250,10 +244,10 @@ var ( Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } - SyncModeFlag = &flags.TextMarshalerFlag{ + SyncModeFlag = &cli.StringFlag{ Name: "syncmode", Usage: `Blockchain sync mode ("snap" or "full")`, - Value: &defaultSyncMode, + Value: ethconfig.Defaults.SyncMode.String(), Category: flags.StateCategory, } GCModeFlag = &cli.StringFlag{ @@ -326,7 +320,7 @@ var ( Usage: "Target EL engine API URL", Category: flags.BeaconCategory, } - BlsyncJWTSecretFlag = &cli.StringFlag{ + BlsyncJWTSecretFlag = &flags.DirectoryFlag{ Name: "blsync.jwtsecret", Usage: "Path to a JWT secret to use for target engine API endpoint", Category: flags.BeaconCategory, @@ -741,11 +735,6 @@ var ( Value: node.DefaultConfig.BatchResponseMaxSize, Category: flags.APICategory, } - EnablePersonal = &cli.BoolFlag{ - Name: "rpc.enabledeprecatedpersonal", - Usage: "Enables the (deprecated) personal namespace", - Category: flags.APICategory, - } // Network Settings MaxPeersFlag = &cli.IntFlag{ @@ -1399,9 +1388,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { if ctx.IsSet(JWTSecretFlag.Name) { cfg.JWTSecret = ctx.String(JWTSecretFlag.Name) } - if ctx.IsSet(EnablePersonal.Name) { - cfg.EnablePersonal = true + log.Warn(fmt.Sprintf("Option --%s is deprecated. The 'personal' RPC namespace has been removed.", EnablePersonal.Name)) } if ctx.IsSet(ExternalSignerFlag.Name) { @@ -1675,7 +1663,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.IsSet(SyncTargetFlag.Name) { cfg.SyncMode = downloader.FullSync // dev sync target forces full sync } else if ctx.IsSet(SyncModeFlag.Name) { - cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) + if err = cfg.SyncMode.UnmarshalText([]byte(ctx.String(SyncModeFlag.Name))); err != nil { + Fatalf("invalid --syncmode flag: %v", err) + } } if ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) @@ -1755,9 +1745,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.SnapshotCache = 0 // Disabled } } - if ctx.IsSet(DocRootFlag.Name) { - cfg.DocRoot = ctx.String(DocRootFlag.Name) - } if ctx.IsSet(VMEnableDebugFlag.Name) { // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) @@ -1903,6 +1890,81 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } } +// MakeBeaconLightConfig constructs a beacon light client config based on the +// related command line flags. +func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig { + var config bparams.ClientConfig + customConfig := ctx.IsSet(BeaconConfigFlag.Name) + CheckExclusive(ctx, MainnetFlag, SepoliaFlag, HoleskyFlag, BeaconConfigFlag) + switch { + case ctx.Bool(MainnetFlag.Name): + config.ChainConfig = *bparams.MainnetLightConfig + case ctx.Bool(SepoliaFlag.Name): + config.ChainConfig = *bparams.SepoliaLightConfig + case ctx.Bool(HoleskyFlag.Name): + config.ChainConfig = *bparams.HoleskyLightConfig + default: + if !customConfig { + config.ChainConfig = *bparams.MainnetLightConfig + } + } + // Genesis root and time should always be specified together with custom chain config + if customConfig { + if !ctx.IsSet(BeaconGenesisRootFlag.Name) { + Fatalf("Custom beacon chain config is specified but genesis root is missing") + } + if !ctx.IsSet(BeaconGenesisTimeFlag.Name) { + Fatalf("Custom beacon chain config is specified but genesis time is missing") + } + if !ctx.IsSet(BeaconCheckpointFlag.Name) { + Fatalf("Custom beacon chain config is specified but checkpoint is missing") + } + config.ChainConfig = bparams.ChainConfig{ + GenesisTime: ctx.Uint64(BeaconGenesisTimeFlag.Name), + } + if c, err := hexutil.Decode(ctx.String(BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 { + copy(config.GenesisValidatorsRoot[:len(c)], c) + } else { + Fatalf("Invalid hex string", "beacon.genesis.gvroot", ctx.String(BeaconGenesisRootFlag.Name), "error", err) + } + configFile := ctx.String(BeaconConfigFlag.Name) + if err := config.ChainConfig.LoadForks(configFile); err != nil { + Fatalf("Could not load beacon chain config", "file", configFile, "error", err) + } + log.Info("Using custom beacon chain config", "file", configFile) + } else { + if ctx.IsSet(BeaconGenesisRootFlag.Name) { + Fatalf("Genesis root is specified but custom beacon chain config is missing") + } + if ctx.IsSet(BeaconGenesisTimeFlag.Name) { + Fatalf("Genesis time is specified but custom beacon chain config is missing") + } + } + // Checkpoint is required with custom chain config and is optional with pre-defined config + if ctx.IsSet(BeaconCheckpointFlag.Name) { + if c, err := hexutil.Decode(ctx.String(BeaconCheckpointFlag.Name)); err == nil && len(c) <= 32 { + copy(config.Checkpoint[:len(c)], c) + } else { + Fatalf("Invalid hex string", "beacon.checkpoint", ctx.String(BeaconCheckpointFlag.Name), "error", err) + } + } + config.Apis = ctx.StringSlice(BeaconApiFlag.Name) + if config.Apis == nil { + Fatalf("Beacon node light client API URL not specified") + } + config.CustomHeader = make(map[string]string) + for _, s := range ctx.StringSlice(BeaconApiHeaderFlag.Name) { + kv := strings.Split(s, ":") + if len(kv) != 2 { + Fatalf("Invalid custom API header entry: %s", s) + } + config.CustomHeader[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1]) + } + config.Threshold = ctx.Int(BeaconThresholdFlag.Name) + config.NoFilter = ctx.Bool(BeaconNoFilterFlag.Name) + return config +} + // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if // no URLs are set. func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index f145f605d6..6209516e05 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -153,6 +153,12 @@ var ( Usage: "Enable expensive metrics collection and reporting (deprecated)", Category: flags.DeprecatedCategory, } + // Deprecated Oct 2024 + EnablePersonal = &cli.BoolFlag{ + Name: "rpc.enabledeprecatedpersonal", + Usage: "This used to enable the 'personal' namespace.", + Category: flags.DeprecatedCategory, + } ) // showDeprecated displays deprecated flags that will be soon removed from the codebase. diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 4ee19c7d4d..cdacf354a5 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -398,21 +398,25 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if parent == nil { return nil, fmt.Errorf("nil parent header for block %d", header.Number) } - preTrie, err := state.Database().OpenTrie(parent.Root) if err != nil { return nil, fmt.Errorf("error opening pre-state tree root: %w", err) } - vktPreTrie, okpre := preTrie.(*trie.VerkleTrie) vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie) + + // The witness is only attached iff both parent and current block are + // using verkle tree. if okpre && okpost { if len(keys) > 0 { - verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys, vktPreTrie.FlatdbNodeResolver) + verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys) if err != nil { return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err) } - block = block.WithWitness(&types.ExecutionWitness{StateDiff: stateDiff, VerkleProof: verkleProof}) + block = block.WithWitness(&types.ExecutionWitness{ + StateDiff: stateDiff, + VerkleProof: verkleProof, + }) } } } diff --git a/console/bridge.go b/console/bridge.go index 37578041ca..c1d7746c02 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -19,15 +19,12 @@ package console import ( "encoding/json" "errors" - "fmt" "io" "reflect" "strings" "time" "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/accounts/scwallet" - "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/internal/jsre" @@ -51,268 +48,6 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ } } -func getJeth(vm *goja.Runtime) *goja.Object { - jeth := vm.Get("jeth") - if jeth == nil { - panic(vm.ToValue("jeth object does not exist")) - } - return jeth.ToObject(vm) -} - -// NewAccount is a wrapper around the personal.newAccount RPC method that uses a -// non-echoing password prompt to acquire the passphrase and executes the original -// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call. -func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) { - var ( - password string - confirm string - err error - ) - switch { - // No password was specified, prompt the user for it - case len(call.Arguments) == 0: - if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil { - return nil, err - } - if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil { - return nil, err - } - if password != confirm { - return nil, errors.New("passwords don't match") - } - // A single string password was specified, use that - case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil: - password = call.Argument(0).ToString().String() - default: - return nil, errors.New("expected 0 or 1 string argument") - } - // Password acquired, execute the call and return - newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount")) - if !callable { - return nil, errors.New("jeth.newAccount is not callable") - } - ret, err := newAccount(goja.Null(), call.VM.ToValue(password)) - if err != nil { - return nil, err - } - return ret, nil -} - -// OpenWallet is a wrapper around personal.openWallet which can interpret and -// react to certain error messages, such as the Trezor PIN matrix request. -func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) { - // Make sure we have a wallet specified to open - if call.Argument(0).ToObject(call.VM).ClassName() != "String" { - return nil, errors.New("first argument must be the wallet URL to open") - } - wallet := call.Argument(0) - - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - passwd = call.VM.ToValue("") - } else { - passwd = call.Argument(1) - } - // Open the wallet and return if successful in itself - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - val, err := openWallet(goja.Null(), wallet, passwd) - if err == nil { - return val, nil - } - - // Wallet open failed, report error unless it's a PIN or PUK entry - switch { - case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()): - val, err = b.readPinAndReopenWallet(call) - if err == nil { - return val, nil - } - val, err = b.readPassphraseAndReopenWallet(call) - if err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()): - // PUK input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter the pairing password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - if val, err = openWallet(goja.Null(), wallet, passwd); err != nil { - if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) { - return nil, err - } - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()): - // PIN unblock requested, fetch PUK and new PIN from the user - var pukpin string - input, err := b.prompter.PromptPassword("Please enter current PUK: ") - if err != nil { - return nil, err - } - pukpin = input - input, err = b.prompter.PromptPassword("Please enter new PIN: ") - if err != nil { - return nil, err - } - pukpin += input - - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()): - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - - default: - // Unknown error occurred, drop to the user - return nil, err - } - return val, nil -} - -func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - input, err := b.prompter.PromptPassword("Please enter your passphrase: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - // Trezor PIN matrix input requested, display the matrix to the user and fetch the data - fmt.Fprintf(b.printer, "Look at the device for number positions\n\n") - fmt.Fprintf(b.printer, "7 | 8 | 9\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "4 | 5 | 6\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "1 | 2 | 3\n\n") - - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that -// uses a non-echoing password prompt to acquire the passphrase and executes the -// original RPC method (saved in jeth.unlockAccount) with it to actually execute -// the RPC call. -func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) { - if len(call.Arguments) < 1 { - return nil, errors.New("usage: unlockAccount(account, [ password, duration ])") - } - - account := call.Argument(0) - // Make sure we have an account specified to unlock. - if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the account to unlock") - } - - // If password is not given or is the null value, prompt the user for it. - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - fmt.Fprintf(b.printer, "Unlock account %s\n", account) - input, err := b.prompter.PromptPassword("Passphrase: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else { - if call.Argument(1).ExportType().Kind() != reflect.String { - return nil, errors.New("password must be a string") - } - passwd = call.Argument(1) - } - - // Third argument is the duration how long the account should be unlocked. - duration := goja.Null() - if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) { - if !isNumber(call.Argument(2)) { - return nil, errors.New("unlock duration must be a number") - } - duration = call.Argument(2) - } - - // Send the request to the backend and return. - unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount")) - if !callable { - return nil, errors.New("jeth.unlockAccount is not callable") - } - return unlockAccount(goja.Null(), account, passwd, duration) -} - -// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password -// prompt to acquire the passphrase and executes the original RPC method (saved in -// jeth.sign) with it to actually execute the RPC call. -func (b *bridge) Sign(call jsre.Call) (goja.Value, error) { - if nArgs := len(call.Arguments); nArgs < 2 { - return nil, errors.New("usage: sign(message, account, [ password ])") - } - var ( - message = call.Argument(0) - account = call.Argument(1) - passwd = call.Argument(2) - ) - - if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the message to sign") - } - if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("second argument must be the account to sign with") - } - - // if the password is not given or null ask the user and ensure password is a string - if goja.IsUndefined(passwd) || goja.IsNull(passwd) { - fmt.Fprintf(b.printer, "Give password for account %s\n", account) - input, err := b.prompter.PromptPassword("Password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else if passwd.ExportType().Kind() != reflect.String { - return nil, errors.New("third argument must be the password to unlock the account") - } - - // Send the request to the backend and return - sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign")) - if !callable { - return nil, errors.New("jeth.sign is not callable") - } - return sign(goja.Null(), message, account, passwd) -} - // Sleep will block the console for the specified number of seconds. func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) { if nArgs := len(call.Arguments); nArgs < 1 { diff --git a/console/console.go b/console/console.go index 5acb4cdccb..b5c77bd78f 100644 --- a/console/console.go +++ b/console/console.go @@ -142,7 +142,6 @@ func (c *Console) init(preload []string) error { // Add bridge overrides for web3.js functionality. c.jsre.Do(func(vm *goja.Runtime) { c.initAdmin(vm, bridge) - c.initPersonal(vm, bridge) }) // Preload JavaScript files. @@ -249,30 +248,6 @@ func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) { } } -// initPersonal redirects account-related API methods through the bridge. -// -// If the console is in interactive mode and the 'personal' API is available, override -// the openWallet, unlockAccount, newAccount and sign methods since these require user -// interaction. The original web3 callbacks are stored in 'jeth'. These will be called -// by the bridge after the prompt and send the original web3 request to the backend. -func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) { - personal := getObject(vm, "personal") - if personal == nil || c.prompter == nil { - return - } - log.Warn("Enabling deprecated personal namespace") - jeth := vm.NewObject() - vm.Set("jeth", jeth) - jeth.Set("openWallet", personal.Get("openWallet")) - jeth.Set("unlockAccount", personal.Get("unlockAccount")) - jeth.Set("newAccount", personal.Get("newAccount")) - jeth.Set("sign", personal.Get("sign")) - personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet)) - personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount)) - personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount)) - personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign)) -} - func (c *Console) clearHistory() { c.history = nil c.prompter.ClearHistory() diff --git a/core/bench_test.go b/core/bench_test.go index 639d36e9ae..6d518e8d3b 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" ) @@ -80,9 +81,15 @@ var ( // value-transfer transaction with n bytes of extra data in each // block. func genValueTx(nbytes int) func(int, *BlockGen) { + // We can reuse the data for all transactions. + // During signing, the method tx.WithSignature(s, sig) + // performs: + // cpy := tx.inner.copy() + // cpy.setSignatureValues(signer.ChainID(), v, r, s) + // After this operation, the data can be reused by the caller. + data := make([]byte, nbytes) return func(i int, gen *BlockGen) { toaddr := common.Address{} - data := make([]byte, nbytes) gas, _ := IntrinsicGas(data, nil, false, false, false, false) signer := gen.Signer() gasPrice := big.NewInt(0) @@ -173,18 +180,16 @@ func genUncles(i int, gen *BlockGen) { func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Create the database in memory or in a temporary directory. var db ethdb.Database - var err error if !disk { db = rawdb.NewMemoryDatabase() } else { - dir := b.TempDir() - db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "", false) + pdb, err := pebble.New(b.TempDir(), 128, 128, "", false) if err != nil { b.Fatalf("cannot create temporary database: %v", err) } + db = rawdb.NewDatabase(pdb) defer db.Close() } - // Generate a chain of b.N blocks using the supplied block // generator function. gspec := &Genesis{ @@ -211,15 +216,27 @@ func BenchmarkChainRead_full_10k(b *testing.B) { benchReadChain(b, true, 10000) } func BenchmarkChainRead_header_100k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchReadChain(b, false, 100000) } func BenchmarkChainRead_full_100k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchReadChain(b, true, 100000) } func BenchmarkChainRead_header_500k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchReadChain(b, false, 500000) } func BenchmarkChainRead_full_500k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchReadChain(b, true, 500000) } func BenchmarkChainWrite_header_10k(b *testing.B) { @@ -235,9 +252,15 @@ func BenchmarkChainWrite_full_100k(b *testing.B) { benchWriteChain(b, true, 100000) } func BenchmarkChainWrite_header_500k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchWriteChain(b, false, 500000) } func BenchmarkChainWrite_full_500k(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } benchWriteChain(b, true, 500000) } @@ -281,11 +304,11 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin func benchWriteChain(b *testing.B, full bool, count uint64) { genesis := &Genesis{Config: params.AllEthashProtocolChanges} for i := 0; i < b.N; i++ { - dir := b.TempDir() - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) + pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false) if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) + b.Fatalf("error opening database: %v", err) } + db := rawdb.NewDatabase(pdb) makeChainForBench(db, genesis, full, count) db.Close() } @@ -294,10 +317,12 @@ func benchWriteChain(b *testing.B, full bool, count uint64) { func benchReadChain(b *testing.B, full bool, count uint64) { dir := b.TempDir() - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) + pdb, err := pebble.New(dir, 1024, 128, "", false) if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) + b.Fatalf("error opening database: %v", err) } + db := rawdb.NewDatabase(pdb) + genesis := &Genesis{Config: params.AllEthashProtocolChanges} makeChainForBench(db, genesis, full, count) db.Close() @@ -308,15 +333,16 @@ func benchReadChain(b *testing.B, full bool, count uint64) { b.ResetTimer() for i := 0; i < b.N; i++ { - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) + pdb, err = pebble.New(dir, 1024, 128, "", false) if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) + b.Fatalf("error opening database: %v", err) } + db = rawdb.NewDatabase(pdb) + chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) if err != nil { b.Fatalf("error creating chain: %v", err) } - for n := uint64(0); n < count; n++ { header := chain.GetHeaderByNumber(n) if full { diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 8a2dfe9f11..6c52d057ad 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" ) @@ -1764,12 +1765,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } defer db.Close() // Might double close, should be fine @@ -1848,12 +1850,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - db, err = rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err = pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) + t.Fatalf("Failed to reopen persistent key-value database: %v", err) + } + db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to reopen persistent freezer database: %v", err) } defer db.Close() @@ -1912,12 +1915,13 @@ func testIssue23496(t *testing.T, scheme string) { datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } defer db.Close() // Might double close, should be fine @@ -1969,12 +1973,13 @@ func testIssue23496(t *testing.T, scheme string) { chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - db, err = rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err = pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) + t.Fatalf("Failed to reopen persistent key-value database: %v", err) + } + db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to reopen persistent freezer database: %v", err) } defer db.Close() diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index b72de33896..424854b2bf 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb/hashdb" @@ -1968,12 +1969,13 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } defer db.Close() diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index 120977f222..1a6fe38af6 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" ) @@ -65,12 +66,13 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } // Initialize a fresh chain var ( @@ -255,12 +257,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { chain.triedb.Close() // Start a new blockchain back up and see where the repair leads us - newdb, err := rawdb.Open(rawdb.OpenOptions{ - Directory: snaptest.datadir, - AncientsDirectory: snaptest.ancient, - }) + pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + newdb, err := rawdb.NewDatabaseWithFreezer(pdb, snaptest.ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } defer newdb.Close() diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 05629cd19f..dc391bb520 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -29,7 +29,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/ethash" @@ -40,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" @@ -2663,12 +2663,13 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) { datadir := t.TempDir() ancient := path.Join(datadir, "ancient") - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) + t.Fatalf("Failed to create persistent key-value database: %v", err) + } + db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + if err != nil { + t.Fatalf("Failed to create persistent freezer database: %v", err) } defer db.Close() @@ -4231,36 +4232,3 @@ func TestPragueRequests(t *testing.T) { t.Fatalf("block %d: failed to insert into chain: %v", n, err) } } - -func BenchmarkReorg(b *testing.B) { - chainLength := b.N - - dir := b.TempDir() - db, err := rawdb.NewLevelDBDatabase(dir, 128, 128, "", false) - if err != nil { - b.Fatalf("cannot create temporary database: %v", err) - } - defer db.Close() - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{benchRootAddr: {Balance: math.BigPow(2, 254)}}, - } - blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) - defer blockchain.Stop() - - // Insert an easy and a difficult chain afterwards - easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), db, chainLength, genValueTx(50000)) - diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), db, chainLength, genValueTx(50000)) - - if _, err := blockchain.InsertChain(easyBlocks); err != nil { - b.Fatalf("failed to insert easy chain: %v", err) - } - b.ResetTimer() - if _, err := blockchain.InsertChain(diffBlocks); err != nil { - b.Fatalf("failed to insert difficult chain: %v", err) - } -} - -// Master: BenchmarkReorg-8 10000 899591 ns/op 820154 B/op 1440 allocs/op 1549443072 bytes of heap used -// WithoutOldChain: BenchmarkReorg-8 10000 1147281 ns/op 943163 B/op 1564 allocs/op 1163870208 bytes of heap used -// WithoutNewChain: BenchmarkReorg-8 10000 1018922 ns/op 943580 B/op 1564 allocs/op 1171890176 bytes of heap used diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 0b9dbe1335..0e986f66e0 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -649,11 +649,15 @@ func makeTestBlocks(nblock int, txsPerBlock int) []*types.Block { // makeTestReceipts creates fake receipts for the ancient write benchmark. func makeTestReceipts(n int, nPerBlock int) []types.Receipts { receipts := make([]*types.Receipt, nPerBlock) + var logs []*types.Log + for i := 0; i < 5; i++ { + logs = append(logs, new(types.Log)) + } for i := 0; i < len(receipts); i++ { receipts[i] = &types.Receipt{ Status: types.ReceiptStatusSuccessful, CumulativeGasUsed: 0x888888888, - Logs: make([]*types.Log, 5), + Logs: logs, } } allReceipts := make([]types.Receipts, n) diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 78dba000fc..1bee455503 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -35,17 +35,17 @@ var newTestHasher = blocktest.NewHasher func TestLookupStorage(t *testing.T) { tests := []struct { name string - writeTxLookupEntriesByBlock func(ethdb.Writer, *types.Block) + writeTxLookupEntriesByBlock func(ethdb.KeyValueWriter, *types.Block) }{ { "DatabaseV6", - func(db ethdb.Writer, block *types.Block) { + func(db ethdb.KeyValueWriter, block *types.Block) { WriteTxLookupEntriesByBlock(db, block) }, }, { "DatabaseV4-V5", - func(db ethdb.Writer, block *types.Block) { + func(db ethdb.KeyValueWriter, block *types.Block) { for _, tx := range block.Transactions() { db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()) } @@ -53,7 +53,7 @@ func TestLookupStorage(t *testing.T) { }, { "DatabaseV3", - func(db ethdb.Writer, block *types.Block) { + func(db ethdb.KeyValueWriter, block *types.Block) { for index, tx := range block.Transactions() { entry := LegacyTxLookupEntry{ BlockHash: block.Hash(), diff --git a/core/rawdb/database.go b/core/rawdb/database.go index e48e523f9e..53418d1646 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -27,9 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/leveldb" "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/log" "github.com/olekukonko/tablewriter" ) @@ -299,37 +297,9 @@ func NewMemoryDatabase() ethdb.Database { return NewDatabase(memorydb.New()) } -// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database -// with an initial starting capacity, but without a freezer moving immutable -// chain segments into cold storage. -func NewMemoryDatabaseWithCap(size int) ethdb.Database { - return NewDatabase(memorydb.NewWithCap(size)) -} - -// NewLevelDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewLevelDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := leveldb.New(file, cache, handles, namespace, readonly) - if err != nil { - return nil, err - } - log.Info("Using LevelDB as the backing database") - return NewDatabase(db), nil -} - -// NewPebbleDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly) - if err != nil { - return nil, err - } - return NewDatabase(db), nil -} - const ( - dbPebble = "pebble" - dbLeveldb = "leveldb" + DBPebble = "pebble" + DBLeveldb = "leveldb" ) // PreexistingDatabase checks the given data directory whether a database is already @@ -343,72 +313,9 @@ func PreexistingDatabase(path string) string { if err != nil { panic(err) // only possible if the pattern is malformed } - return dbPebble + return DBPebble } - return dbLeveldb -} - -// OpenOptions contains the options to apply when opening a database. -// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used. -type OpenOptions struct { - Type string // "leveldb" | "pebble" - Directory string // the datadir - AncientsDirectory string // the ancients-dir - Namespace string // the namespace for database relevant metrics - Cache int // the capacity(in megabytes) of the data caching - Handles int // number of files to be open simultaneously - ReadOnly bool -} - -// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. -// -// type == null type != null -// +---------------------------------------- -// db is non-existent | pebble default | specified type -// db is existent | from db | specified type (if compatible) -func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) { - // Reject any unsupported database type - if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble { - return nil, fmt.Errorf("unknown db.engine %v", o.Type) - } - // Retrieve any pre-existing database's type and use that or the requested one - // as long as there's no conflict between the two types - existingDb := PreexistingDatabase(o.Directory) - if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { - return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) - } - if o.Type == dbPebble || existingDb == dbPebble { - log.Info("Using pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } - if o.Type == dbLeveldb || existingDb == dbLeveldb { - log.Info("Using leveldb as the backing database") - return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } - // No pre-existing database, no user-requested one either. Default to Pebble. - log.Info("Defaulting to pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) -} - -// Open opens both a disk-based key-value database such as leveldb or pebble, but also -// integrates it with a freezer database -- if the AncientDir option has been -// set on the provided OpenOptions. -// The passed o.AncientDir indicates the path of root ancient directory where -// the chain freezer can be opened. -func Open(o OpenOptions) (ethdb.Database, error) { - kvdb, err := openKeyValueDatabase(o) - if err != nil { - return nil, err - } - if len(o.AncientsDirectory) == 0 { - return kvdb, nil - } - frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly) - if err != nil { - kvdb.Close() - return nil, err - } - return frdb, nil + return DBLeveldb } type counter uint64 diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 1b8df958d1..d6370cee33 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -58,8 +58,9 @@ const freezerTableSize = 2 * 1000 * 1000 * 1000 // - The append-only nature ensures that disk writes are minimized. // - The in-order data ensures that disk reads are always optimized. type Freezer struct { - frozen atomic.Uint64 // Number of items already frozen - tail atomic.Uint64 // Number of the first stored item in the freezer + datadir string + frozen atomic.Uint64 // Number of items already frozen + tail atomic.Uint64 // Number of the first stored item in the freezer // This lock synchronizes writers and the truncate operation, as well as // the "atomic" (batched) read operations. @@ -109,6 +110,7 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui } // Open all the supported data tables freezer := &Freezer{ + datadir: datadir, readonly: readonly, tables: make(map[string]*freezerTable), instanceLock: lock, @@ -172,6 +174,11 @@ func (f *Freezer) Close() error { return nil } +// AncientDatadir returns the path of the ancient store. +func (f *Freezer) AncientDatadir() (string, error) { + return f.datadir, nil +} + // HasAncient returns an indicator whether the specified ancient data exists // in the freezer. func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) { diff --git a/core/rawdb/freezer_memory.go b/core/rawdb/freezer_memory.go index ee4f553919..2d3dbb07dd 100644 --- a/core/rawdb/freezer_memory.go +++ b/core/rawdb/freezer_memory.go @@ -419,3 +419,9 @@ func (f *MemoryFreezer) Reset() error { f.items, f.tail = 0, 0 return nil } + +// AncientDatadir returns the path of the ancient store. +// Since the memory freezer is ephemeral, an empty string is returned. +func (f *MemoryFreezer) AncientDatadir() (string, error) { + return "", nil +} diff --git a/core/rawdb/freezer_resettable.go b/core/rawdb/freezer_resettable.go index b147995066..7c77a06efc 100644 --- a/core/rawdb/freezer_resettable.go +++ b/core/rawdb/freezer_resettable.go @@ -202,6 +202,14 @@ func (f *resettableFreezer) Sync() error { return f.freezer.Sync() } +// AncientDatadir returns the path of the ancient store. +func (f *resettableFreezer) AncientDatadir() (string, error) { + f.lock.RLock() + defer f.lock.RUnlock() + + return f.freezer.AncientDatadir() +} + // cleanup removes the directory located in the specified path // has the name with deletion marker suffix. func cleanup(path string) error { diff --git a/core/rawdb/table.go b/core/rawdb/table.go index bc1d354d10..1a9060b636 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -129,6 +129,12 @@ func (t *table) Delete(key []byte) error { return t.db.Delete(append([]byte(t.prefix), key...)) } +// DeleteRange deletes all of the keys (and values) in the range [start,end) +// (inclusive on start, exclusive on end). +func (t *table) DeleteRange(start, end []byte) error { + return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...)) +} + // NewIterator creates a binary-alphabetical iterator over a subset // of database content with a particular key prefix, starting at a particular // initial key (or after, if it does not exist). diff --git a/core/state/access_events.go b/core/state/access_events.go index 7f67df64eb..b745c383b1 100644 --- a/core/state/access_events.go +++ b/core/state/access_events.go @@ -117,7 +117,7 @@ func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address) return gas } -// ContractCreateCPreheck charges access costs before +// ContractCreatePreCheckGas charges access costs before // a contract creation is initiated. It is just reads, because the // address collision is done before the transfer, and so no write // are guaranteed to happen at this point. diff --git a/core/state/database.go b/core/state/database.go index de61dee036..0d8acec35a 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -186,9 +186,9 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) { // is optional and may be partially useful if it's not fully // generated. if db.snap != nil { - sr, err := newStateReader(stateRoot, db.snap) - if err == nil { - readers = append(readers, sr) // snap reader is optional + snap := db.snap.Snapshot(stateRoot) + if snap != nil { + readers = append(readers, newStateReader(snap)) // snap reader is optional } } // Set up the trie reader, which is expected to always be available diff --git a/core/state/reader.go b/core/state/reader.go index 6bddefc2a7..85842adde8 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -21,13 +21,13 @@ import ( "maps" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/utils" "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/database" ) // Reader defines the interface for accessing accounts and storage slots @@ -52,23 +52,18 @@ type Reader interface { Copy() Reader } -// stateReader is a wrapper over the state snapshot and implements the Reader -// interface. It provides an efficient way to access flat state. +// stateReader wraps a database state reader. type stateReader struct { - snap snapshot.Snapshot - buff crypto.KeccakState + reader database.StateReader + buff crypto.KeccakState } -// newStateReader constructs a flat state reader with on the specified state root. -func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) { - snap := snaps.Snapshot(root) - if snap == nil { - return nil, errors.New("snapshot is not available") - } +// newStateReader constructs a state reader with on the given state root. +func newStateReader(reader database.StateReader) *stateReader { return &stateReader{ - snap: snap, - buff: crypto.NewKeccakState(), - }, nil + reader: reader, + buff: crypto.NewKeccakState(), + } } // Account implements Reader, retrieving the account specified by the address. @@ -78,18 +73,18 @@ func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error // // The returned account might be nil if it's not existent. func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) { - ret, err := r.snap.Account(crypto.HashData(r.buff, addr.Bytes())) + account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes())) if err != nil { return nil, err } - if ret == nil { + if account == nil { return nil, nil } acct := &types.StateAccount{ - Nonce: ret.Nonce, - Balance: ret.Balance, - CodeHash: ret.CodeHash, - Root: common.BytesToHash(ret.Root), + Nonce: account.Nonce, + Balance: account.Balance, + CodeHash: account.CodeHash, + Root: common.BytesToHash(account.Root), } if len(acct.CodeHash) == 0 { acct.CodeHash = types.EmptyCodeHash.Bytes() @@ -110,7 +105,7 @@ func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { addrHash := crypto.HashData(r.buff, addr.Bytes()) slotHash := crypto.HashData(r.buff, key.Bytes()) - ret, err := r.snap.Storage(addrHash, slotHash) + ret, err := r.reader.Storage(addrHash, slotHash) if err != nil { return common.Hash{}, err } @@ -131,8 +126,8 @@ func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash // Copy implements Reader, returning a deep-copied snap reader. func (r *stateReader) Copy() Reader { return &stateReader{ - snap: r.snap, - buff: crypto.NewKeccakState(), + reader: r.reader, + buff: crypto.NewKeccakState(), } } diff --git a/core/state/statedb.go b/core/state/statedb.go index 0183c14480..d855e5626d 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -341,6 +341,9 @@ func (s *StateDB) TxIndex() int { func (s *StateDB) GetCode(addr common.Address) []byte { stateObject := s.getStateObject(addr) if stateObject != nil { + if s.witness != nil { + s.witness.AddCode(stateObject.Code()) + } return stateObject.Code() } return nil @@ -349,6 +352,9 @@ func (s *StateDB) GetCode(addr common.Address) []byte { func (s *StateDB) GetCodeSize(addr common.Address) int { stateObject := s.getStateObject(addr) if stateObject != nil { + if s.witness != nil { + s.witness.AddCode(stateObject.Code()) + } return stateObject.CodeSize() } return 0 @@ -1062,7 +1068,8 @@ func (s *StateDB) handleDestruction() (map[common.Hash]*accountDelete, []*trieno deletes[addrHash] = op // Short circuit if the origin storage was empty. - if prev.Root == types.EmptyRootHash { + + if prev.Root == types.EmptyRootHash || s.db.TrieDB().IsVerkle() { continue } // Remove storage slots belonging to the account. diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index e7ec0228f0..2314a02989 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -174,7 +174,7 @@ func (s *hookedStateDB) Snapshot() int { } func (s *hookedStateDB) AddPreimage(hash common.Hash, bytes []byte) { - s.inner.Snapshot() + s.inner.AddPreimage(hash, bytes) } func (s *hookedStateDB) Witness() *stateless.Witness { @@ -222,22 +222,46 @@ func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value } func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int { - prev := s.inner.SelfDestruct(address) - if !prev.IsZero() { - if s.hooks.OnBalanceChange != nil { - s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) - } + var prevCode []byte + var prevCodeHash common.Hash + + if s.hooks.OnCodeChange != nil { + prevCode = s.inner.GetCode(address) + prevCodeHash = s.inner.GetCodeHash(address) } + + prev := s.inner.SelfDestruct(address) + + if s.hooks.OnBalanceChange != nil && !prev.IsZero() { + s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) + } + + if s.hooks.OnCodeChange != nil && len(prevCode) > 0 { + s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + } + return prev } func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) { - prev, changed := s.inner.SelfDestruct6780(address) - if !prev.IsZero() && changed { - if s.hooks.OnBalanceChange != nil { - s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) - } + var prevCode []byte + var prevCodeHash common.Hash + + if s.hooks.OnCodeChange != nil { + prevCodeHash = s.inner.GetCodeHash(address) + prevCode = s.inner.GetCode(address) } + + prev, changed := s.inner.SelfDestruct6780(address) + + if s.hooks.OnBalanceChange != nil && changed && !prev.IsZero() { + s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) + } + + if s.hooks.OnCodeChange != nil && changed && len(prevCode) > 0 { + s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + } + return prev, changed } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 2a16ef2cfb..f3d2304690 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -18,7 +18,6 @@ package core import ( "crypto/ecdsa" - "encoding/binary" "math" "math/big" "testing" @@ -30,14 +29,11 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-verkle" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" ) @@ -426,193 +422,3 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr } return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)) } - -var ( - code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`) - intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, true, true, true, true) - // A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness - // will not contain that copied data. - // Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985 - codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`) - intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, true, true, true, true) -) - -func TestProcessVerkle(t *testing.T) { - var ( - config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - Ethash: new(params.EthashConfig), - ShanghaiTime: u64(0), - VerkleTime: u64(0), - TerminalTotalDifficulty: common.Big0, - } - signer = types.LatestSigner(config) - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain - coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") - gspec = &Genesis{ - Config: config, - Alloc: GenesisAlloc{ - coinbase: GenesisAccount{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: 0, - }, - }, - } - ) - // Verkle trees use the snapshot, which must be enabled before the - // data is saved into the tree+database. - // genesis := gspec.MustCommit(bcdb, triedb) - cacheConfig := DefaultCacheConfigWithScheme("path") - cacheConfig.SnapshotLimit = 0 - blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) - defer blockchain.Stop() - - txCost1 := params.TxGas - txCost2 := params.TxGas - contractCreationCost := intrinsicContractCreationGas + - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* creation with value */ - 739 /* execution costs */ - codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas + - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (tx) */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at pc=0x20) */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */ - params.WitnessChunkReadCost + /* SLOAD in constructor */ - params.WitnessChunkWriteCost + /* SSTORE in constructor */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at PC=0x121) */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */ - params.WitnessChunkReadCost + /* SLOAD in constructor */ - params.WitnessChunkWriteCost + /* SSTORE in constructor */ - params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash for tx creation */ - 15*(params.WitnessChunkReadCost+params.WitnessChunkWriteCost) + /* code chunks #0..#14 */ - 4844 /* execution costs */ - blockGasUsagesExpected := []uint64{ - txCost1*2 + txCost2, - txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas, - } - _, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { - gen.SetPoS() - - // TODO need to check that the tx cost provided is the exact amount used (no remaining left-over) - tx, _ := types.SignTx(types.NewTransaction(uint64(i)*3, common.Address{byte(i), 2, 3}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) - gen.AddTx(tx) - tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+1, common.Address{}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) - gen.AddTx(tx) - tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+2, common.Address{}, big.NewInt(0), txCost2, big.NewInt(875000000), nil), signer, testKey) - gen.AddTx(tx) - - // Add two contract creations in block #2 - if i == 1 { - tx, _ = types.SignTx(types.NewContractCreation(6, big.NewInt(16), 3000000, big.NewInt(875000000), code), signer, testKey) - gen.AddTx(tx) - - tx, _ = types.SignTx(types.NewContractCreation(7, big.NewInt(0), 3000000, big.NewInt(875000000), codeWithExtCodeCopy), signer, testKey) - gen.AddTx(tx) - } - }) - - // Check proof for both blocks - err := verkle.Verify(proofs[0], gspec.ToBlock().Root().Bytes(), chain[0].Root().Bytes(), statediffs[0]) - if err != nil { - t.Fatal(err) - } - err = verkle.Verify(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), statediffs[1]) - if err != nil { - t.Fatal(err) - } - - t.Log("verified verkle proof, inserting blocks into the chain") - - endnum, err := blockchain.InsertChain(chain) - if err != nil { - t.Fatalf("block %d imported with error: %v", endnum, err) - } - - for i := 0; i < 2; i++ { - b := blockchain.GetBlockByNumber(uint64(i) + 1) - if b == nil { - t.Fatalf("expected block %d to be present in chain", i+1) - } - if b.Hash() != chain[i].Hash() { - t.Fatalf("block #%d not found at expected height", b.NumberU64()) - } - if b.GasUsed() != blockGasUsagesExpected[i] { - t.Fatalf("expected block #%d txs to use %d, got %d\n", b.NumberU64(), blockGasUsagesExpected[i], b.GasUsed()) - } - } -} - -func TestProcessParentBlockHash(t *testing.T) { - var ( - chainConfig = params.MergedTestChainConfig - hashA = common.Hash{0x01} - hashB = common.Hash{0x02} - header = &types.Header{ParentHash: hashA, Number: big.NewInt(2), Difficulty: big.NewInt(0)} - parent = &types.Header{ParentHash: hashB, Number: big.NewInt(1), Difficulty: big.NewInt(0)} - coinbase = common.Address{} - ) - test := func(statedb *state.StateDB) { - statedb.SetNonce(params.HistoryStorageAddress, 1) - statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode) - statedb.IntermediateRoot(true) - - vmContext := NewEVMBlockContext(header, nil, &coinbase) - evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{}) - ProcessParentBlockHash(header.ParentHash, evm, statedb) - - vmContext = NewEVMBlockContext(parent, nil, &coinbase) - evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{}) - ProcessParentBlockHash(parent.ParentHash, evm, statedb) - - // make sure that the state is correct - if have := getParentBlockHash(statedb, 1); have != hashA { - t.Errorf("want parent hash %v, have %v", hashA, have) - } - if have := getParentBlockHash(statedb, 0); have != hashB { - t.Errorf("want parent hash %v, have %v", hashB, have) - } - } - t.Run("MPT", func(t *testing.T) { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) - test(statedb) - }) - t.Run("Verkle", func(t *testing.T) { - db := rawdb.NewMemoryDatabase() - cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) - cacheConfig.SnapshotLimit = 0 - triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) - statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil)) - test(statedb) - }) -} - -func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash { - ringIndex := number % params.HistoryServeWindow - var key common.Hash - binary.BigEndian.PutUint64(key[24:], ringIndex) - return statedb.GetState(params.HistoryStorageAddress, key) -} diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 76cb6801fa..0352ea9783 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -318,6 +318,10 @@ type BlobPool struct { 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) + // 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 } @@ -329,12 +333,13 @@ func New(config Config, chain BlockChain) *BlobPool { // Create the transaction pool with its initial settings return &BlobPool{ - config: config, - signer: types.LatestSigner(chain.Config()), - chain: chain, - lookup: newLookup(), - index: make(map[common.Address][]*blobTxMeta), - spent: make(map[common.Address]*uint256.Int), + config: config, + signer: types.LatestSigner(chain.Config()), + chain: chain, + lookup: newLookup(), + index: make(map[common.Address][]*blobTxMeta), + spent: make(map[common.Address]*uint256.Int), + txValidationFn: txpool.ValidateTransaction, } } @@ -1090,7 +1095,8 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error { MaxSize: txMaxSize, MinTip: p.gasTip.ToBig(), } - if err := txpool.ValidateTransaction(tx, p.head, p.signer, baseOpts); err != nil { + + if err := p.txValidationFn(tx, p.head, p.signer, baseOpts); err != nil { return err } // Ensure the transaction adheres to the stateful pool filters (nonce, balance) diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 721f7c6c2e..e4441bec5d 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -1449,11 +1449,29 @@ func TestAdd(t *testing.T) { } } +// fakeBilly is a billy.Database implementation which just drops data on the floor. +type fakeBilly struct { + billy.Database + count uint64 +} + +func (f *fakeBilly) Put(data []byte) (uint64, error) { + f.count++ + return f.count, nil +} + +var _ billy.Database = (*fakeBilly)(nil) + // Benchmarks the time it takes to assemble the lazy pending transaction list // from the pool contents. func BenchmarkPoolPending100Mb(b *testing.B) { benchmarkPoolPending(b, 100_000_000) } func BenchmarkPoolPending1GB(b *testing.B) { benchmarkPoolPending(b, 1_000_000_000) } -func BenchmarkPoolPending10GB(b *testing.B) { benchmarkPoolPending(b, 10_000_000_000) } +func BenchmarkPoolPending10GB(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } + benchmarkPoolPending(b, 10_000_000_000) +} func benchmarkPoolPending(b *testing.B, datacap uint64) { // Calculate the maximum number of transaction that would fit into the pool @@ -1477,6 +1495,15 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) { if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { b.Fatalf("failed to create blob pool: %v", err) } + // 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 + 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 // same price and everything to maximize the worst case scenario for i := 0; i < int(capacity); i++ { diff --git a/core/txpool/blobpool/evictheap_test.go b/core/txpool/blobpool/evictheap_test.go index 1cf577cb00..b03dd83d69 100644 --- a/core/txpool/blobpool/evictheap_test.go +++ b/core/txpool/blobpool/evictheap_test.go @@ -239,9 +239,25 @@ func BenchmarkPriceHeapOverflow10MB(b *testing.B) { benchmarkPriceHeapOverflow( func BenchmarkPriceHeapOverflow100MB(b *testing.B) { benchmarkPriceHeapOverflow(b, 100*1024*1024) } func BenchmarkPriceHeapOverflow1GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 1024*1024*1024) } func BenchmarkPriceHeapOverflow10GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 10*1024*1024*1024) } -func BenchmarkPriceHeapOverflow25GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 25*1024*1024*1024) } -func BenchmarkPriceHeapOverflow50GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 50*1024*1024*1024) } -func BenchmarkPriceHeapOverflow100GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 100*1024*1024*1024) } + +func BenchmarkPriceHeapOverflow25GB(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } + benchmarkPriceHeapOverflow(b, 25*1024*1024*1024) +} +func BenchmarkPriceHeapOverflow50GB(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } + benchmarkPriceHeapOverflow(b, 50*1024*1024*1024) +} +func BenchmarkPriceHeapOverflow100GB(b *testing.B) { + if testing.Short() { + b.Skip("Skipping in short-mode") + } + benchmarkPriceHeapOverflow(b, 100*1024*1024*1024) +} func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) { // Calculate how many unique transactions we can fit into the provided disk diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 363fa29c02..54ae3be569 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -358,7 +358,7 @@ func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool) []error { for i, split := range splits { // If the transaction was rejected by all subpools, mark it unsupported if split == -1 { - errs[i] = core.ErrTxTypeNotSupported + errs[i] = fmt.Errorf("%w: received type %d", core.ErrTxTypeNotSupported, txs[i].Type()) continue } // Find which subpool handled it and pull in the corresponding error diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 7fd5f8bc79..33b383d5cf 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -47,6 +47,11 @@ type ValidationOptions struct { MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool } +// ValidationFunction is an method type which the pools use to perform the tx-validations which do not +// require state access. Production code typically uses ValidateTransaction, whereas testing-code +// might choose to instead use something else, e.g. to always fail or avoid heavy cpu usage. +type ValidationFunction func(tx *types.Transaction, head *types.Header, signer types.Signer, opts *ValidationOptions) error + // ValidateTransaction is a helper method to check whether a transaction is valid // according to the consensus rules, but does not check state-dependent validation // (balance, nonce, etc). @@ -99,7 +104,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Make sure the transaction is signed properly if _, err := types.Sender(signer, tx); err != nil { - return ErrInvalidSender + return fmt.Errorf("%w: %v", ErrInvalidSender, err) } // Ensure the transaction has more gas than the bare minimum needed to cover // the transaction metadata diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go new file mode 100644 index 0000000000..5a4210cdab --- /dev/null +++ b/core/verkle_witness_test.go @@ -0,0 +1,1087 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package core + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "math/big" + "slices" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie/utils" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-verkle" + "github.com/holiman/uint256" +) + +var ( + testVerkleChainConfig = ¶ms.ChainConfig{ + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Ethash: new(params.EthashConfig), + ShanghaiTime: u64(0), + VerkleTime: u64(0), + TerminalTotalDifficulty: common.Big0, + // TODO uncomment when proof generation is merged + // ProofInBlocks: true, + } + testKaustinenLikeChainConfig = ¶ms.ChainConfig{ + ChainID: big.NewInt(69420), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Ethash: new(params.EthashConfig), + ShanghaiTime: u64(0), + VerkleTime: u64(0), + TerminalTotalDifficulty: common.Big0, + } +) + +func TestProcessVerkle(t *testing.T) { + var ( + code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`) + intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, true, true, true, true) + // A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness + // will not contain that copied data. + // Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985 + codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`) + intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, true, true, true, true) + signer = types.LatestSigner(testVerkleChainConfig) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain + coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") + gspec = &Genesis{ + Config: testVerkleChainConfig, + Alloc: GenesisAlloc{ + coinbase: { + Balance: big.NewInt(1000000000000000000), // 1 ether + Nonce: 0, + }, + params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0}, + params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0}, + params.WithdrawalQueueAddress: {Nonce: 1, Code: params.WithdrawalQueueCode, Balance: common.Big0}, + params.ConsolidationQueueAddress: {Nonce: 1, Code: params.ConsolidationQueueCode, Balance: common.Big0}, + }, + } + ) + // Verkle trees use the snapshot, which must be enabled before the + // data is saved into the tree+database. + // genesis := gspec.MustCommit(bcdb, triedb) + cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) + cacheConfig.SnapshotLimit = 0 + blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + defer blockchain.Stop() + + txCost1 := params.TxGas + txCost2 := params.TxGas + contractCreationCost := intrinsicContractCreationGas + + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* creation with value */ + 739 /* execution costs */ + codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas + + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (tx) */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at pc=0x20) */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */ + params.WitnessChunkReadCost + /* SLOAD in constructor */ + params.WitnessChunkWriteCost + /* SSTORE in constructor */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at PC=0x121) */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */ + params.WitnessChunkReadCost + /* SLOAD in constructor */ + params.WitnessChunkWriteCost + /* SSTORE in constructor */ + params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash for tx creation */ + 15*(params.WitnessChunkReadCost+params.WitnessChunkWriteCost) + /* code chunks #0..#14 */ + 4844 /* execution costs */ + blockGasUsagesExpected := []uint64{ + txCost1*2 + txCost2, + txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas, + } + _, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { + gen.SetPoS() + + // TODO need to check that the tx cost provided is the exact amount used (no remaining left-over) + tx, _ := types.SignTx(types.NewTransaction(uint64(i)*3, common.Address{byte(i), 2, 3}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+1, common.Address{}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+2, common.Address{}, big.NewInt(0), txCost2, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + + // Add two contract creations in block #2 + if i == 1 { + tx, _ = types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 6, + Value: big.NewInt(16), + Gas: 3000000, + GasPrice: big.NewInt(875000000), + Data: code, + }) + gen.AddTx(tx) + + tx, _ = types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 7, + Value: big.NewInt(0), + Gas: 3000000, + GasPrice: big.NewInt(875000000), + Data: codeWithExtCodeCopy, + }) + gen.AddTx(tx) + } + }) + + // Check proof for both blocks + err := verkle.Verify(proofs[0], gspec.ToBlock().Root().Bytes(), chain[0].Root().Bytes(), statediffs[0]) + if err != nil { + t.Fatal(err) + } + err = verkle.Verify(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), statediffs[1]) + if err != nil { + t.Fatal(err) + } + + t.Log("verified verkle proof, inserting blocks into the chain") + + endnum, err := blockchain.InsertChain(chain) + if err != nil { + t.Fatalf("block %d imported with error: %v", endnum, err) + } + + for i := 0; i < 2; i++ { + b := blockchain.GetBlockByNumber(uint64(i) + 1) + if b == nil { + t.Fatalf("expected block %d to be present in chain", i+1) + } + if b.Hash() != chain[i].Hash() { + t.Fatalf("block #%d not found at expected height", b.NumberU64()) + } + if b.GasUsed() != blockGasUsagesExpected[i] { + t.Fatalf("expected block #%d txs to use %d, got %d\n", b.NumberU64(), blockGasUsagesExpected[i], b.GasUsed()) + } + } +} + +func TestProcessParentBlockHash(t *testing.T) { + // This test uses blocks where, + // block 1 parent hash is 0x0100.... + // block 2 parent hash is 0x0200.... + // etc + checkBlockHashes := func(statedb *state.StateDB) { + statedb.SetNonce(params.HistoryStorageAddress, 1) + statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode) + // Process n blocks, from 1 .. num + var num = 2 + for i := 1; i <= num; i++ { + header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)} + vmContext := NewEVMBlockContext(header, nil, new(common.Address)) + evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, params.MergedTestChainConfig, vm.Config{}) + ProcessParentBlockHash(header.ParentHash, evm, statedb) + } + // Read block hashes for block 0 .. num-1 + for i := 0; i < num; i++ { + have, want := getContractStoredBlockHash(statedb, uint64(i)), common.Hash{byte(i + 1)} + if have != want { + t.Errorf("block %d, have parent hash %v, want %v", i, have, want) + } + } + } + t.Run("MPT", func(t *testing.T) { + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + checkBlockHashes(statedb) + }) + t.Run("Verkle", func(t *testing.T) { + db := rawdb.NewMemoryDatabase() + cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) + cacheConfig.SnapshotLimit = 0 + triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) + statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil)) + checkBlockHashes(statedb) + }) +} + +// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number' +func getContractStoredBlockHash(statedb *state.StateDB, number uint64) common.Hash { + ringIndex := number % params.HistoryServeWindow + var key common.Hash + binary.BigEndian.PutUint64(key[24:], ringIndex) + return statedb.GetState(params.HistoryStorageAddress, key) +} + +// TestProcessVerkleInvalidContractCreation checks for several modes of contract creation failures +func TestProcessVerkleInvalidContractCreation(t *testing.T) { + var ( + account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e") + account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d") + gspec = verkleTestGenesis(testKaustinenLikeChainConfig) + ) + // slightly modify it to suit the live txs from the testnet + gspec.Alloc[account2] = types.Account{ + Balance: big.NewInt(1000000000000000000), // 1 ether + Nonce: 1, + } + + // Create two blocks that reproduce what is happening on kaustinen. + // - The first block contains two failing contract creation transactions, that + // write to storage before they revert. + // + // - The second block contains a single failing contract creation transaction, + // that fails right off the bat. + _, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { + gen.SetPoS() + + if i == 0 { + for _, rlpData := range []string{ + // SSTORE at slot 41 and reverts + "f8d48084479c2c18830186a08080b8806000602955bda3f9600060ca55600060695523b360006039551983576000601255b0620c2fde2c592ac2600060bc55e0ac6000606455a63e22600060e655eb607e605c5360a2605d5360c7605e53601d605f5360eb606053606b606153608e60625360816063536079606453601e60655360fc60665360b7606753608b60685383021e7ca0cc20c65a97d2e526b8ec0f4266e8b01bdcde43b9aeb59d8bfb44e8eb8119c109a07a8e751813ae1b2ce734960dbc39a4f954917d7822a2c5d1dca18b06c584131f", + // SSTORE at slot 133 and reverts + "02f8db83010f2c01843b9aca0084479c2c18830186a08080b88060006085553fad6000600a55600060565555600060b55506600060cf557f1b8b38183e7bd1bdfaa7123c5a4976e54cce0e42049d841411978fd3595e25c66019527f0538943712953cf08900aae40222a40b2d5a4ac8075ad8cf0870e2be307edbb96039527f9f3174ff85024747041ae7a611acffb987c513c088d90ab288aec080a0cd6ac65ce2cb0a912371f6b5a551ba8caffc22ec55ad4d3cb53de41d05eb77b6a02e0dfe8513dfa6ec7bfd7eda6f5c0dac21b39b982436045e128cec46cfd3f960", + // this one is a simple transfer that succeeds, necessary to get the correct nonce in the other block. + "f8e80184479c2c18830186a094bbbbde4ca27f83fc18aa108170547ff57675936a80b8807ff71f7c15faadb969a76a5f54a81a0117e1e743cb7f24e378eda28442ea4c6eb6604a527fb5409e5718d44e23bfffac926e5ea726067f772772e7e19446acba0c853f62f5606a526020608a536088608b536039608c536004608d5360af608e537f7f7675d9f210e0a61564e6d11e7cd75f5bc9009ac9f6b94a0fc63035441a83021e7ba04a4a172d81ebb02847829b76a387ac09749c8b65668083699abe20c887fb9efca07c5b1a990702ec7b31a5e8e3935cd9a77649f8c25a84131229e24ab61aec6093", + } { + var tx = new(types.Transaction) + if err := tx.UnmarshalBinary(common.Hex2Bytes(rlpData)); err != nil { + t.Fatal(err) + } + gen.AddTx(tx) + } + } else { + var tx = new(types.Transaction) + // immediately reverts + if err := tx.UnmarshalBinary(common.Hex2Bytes("01f8d683010f2c028443ad7d0e830186a08080b880b00e7fa3c849dce891cce5fae8a4c46cbb313d6aec0c0ffe7863e05fb7b22d4807674c6055527ffbfcb0938f3e18f7937aa8fa95d880afebd5c4cec0d85186095832d03c85cf8a60755260ab60955360cf6096536066609753606e60985360fa609953609e609a53608e609b536024609c5360f6609d536072609e5360a4609fc080a08fc6f7101f292ff1fb0de8ac69c2d320fbb23bfe61cf327173786ea5daee6e37a044c42d91838ef06646294bf4f9835588aee66243b16a66a2da37641fae4c045f")); err != nil { + t.Fatal(err) + } + gen.AddTx(tx) + } + }) + + tx1ContractAddress := crypto.CreateAddress(account1, 0) + tx1ContractStem := utils.GetTreeKey(tx1ContractAddress[:], uint256.NewInt(0), 105) + tx1ContractStem = tx1ContractStem[:31] + + tx2ContractAddress := crypto.CreateAddress(account2, 1) + tx2SlotKey := [32]byte{} + tx2SlotKey[31] = 133 + tx2ContractStem := utils.StorageSlotKey(tx2ContractAddress[:], tx2SlotKey[:]) + tx2ContractStem = tx2ContractStem[:31] + + eip2935Stem := utils.GetTreeKey(params.HistoryStorageAddress[:], uint256.NewInt(0), 0) + eip2935Stem = eip2935Stem[:31] + + // Check that the witness contains what we expect: a storage entry for each of the two contract + // creations that failed: one at 133 for the 2nd tx, and one at 105 for the first tx. + for _, stemStateDiff := range statediffs[0] { + // Check that the slot number 133, which is overflowing the account header, + // is present. Note that the offset of the 2nd group (first group after the + // header) is skipping the first 64 values, hence we still have an offset + // of 133, and not 133 - 64. + if bytes.Equal(stemStateDiff.Stem[:], tx2ContractStem[:]) { + for _, suffixDiff := range stemStateDiff.SuffixDiffs { + if suffixDiff.Suffix != 133 { + t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix) + } + if suffixDiff.CurrentValue != nil { + t.Fatalf("invalid prestate value found for %x in block #1: %v != nil\n", stemStateDiff.Stem, suffixDiff.CurrentValue) + } + if suffixDiff.NewValue != nil { + t.Fatalf("invalid poststate value found for %x in block #1: %v != nil\n", stemStateDiff.Stem, suffixDiff.NewValue) + } + } + } else if bytes.Equal(stemStateDiff.Stem[:], tx1ContractStem) { + // For this contract creation, check that only the accound header and storage slot 41 + // are found in the witness. + for _, suffixDiff := range stemStateDiff.SuffixDiffs { + if suffixDiff.Suffix != 105 && suffixDiff.Suffix != 0 && suffixDiff.Suffix != 1 { + t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix) + } + } + } else if bytes.Equal(stemStateDiff.Stem[:], eip2935Stem) { + // Check the eip 2935 group of leaves. + // Check that only one leaf was accessed, and is present in the witness. + if len(stemStateDiff.SuffixDiffs) > 1 { + t.Fatalf("invalid suffix diff count found for BLOCKHASH contract: %d != 1", len(stemStateDiff.SuffixDiffs)) + } + // Check that this leaf is the first storage slot + if stemStateDiff.SuffixDiffs[0].Suffix != 64 { + t.Fatalf("invalid suffix diff value found for BLOCKHASH contract: %d != 64", stemStateDiff.SuffixDiffs[0].Suffix) + } + // check that the prestate value is nil and that the poststate value isn't. + if stemStateDiff.SuffixDiffs[0].CurrentValue != nil { + t.Fatalf("non-nil current value in BLOCKHASH contract insert: %x", stemStateDiff.SuffixDiffs[0].CurrentValue) + } + if stemStateDiff.SuffixDiffs[0].NewValue == nil { + t.Fatalf("nil new value in BLOCKHASH contract insert") + } + if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() { + t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash()) + } + } else { + // For all other entries present in the witness, check that nothing beyond + // the account header was accessed. + for _, suffixDiff := range stemStateDiff.SuffixDiffs { + if suffixDiff.Suffix > 2 { + t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix) + } + } + } + } + + // Check that no account has a value above 4 in the 2nd block as no storage nor + // code should make it to the witness. + for _, stemStateDiff := range statediffs[1] { + for _, suffixDiff := range stemStateDiff.SuffixDiffs { + if bytes.Equal(stemStateDiff.Stem[:], eip2935Stem) { + // BLOCKHASH contract stem + if len(stemStateDiff.SuffixDiffs) > 1 { + t.Fatalf("invalid suffix diff count found for BLOCKHASH contract at block #2: %d != 1", len(stemStateDiff.SuffixDiffs)) + } + if stemStateDiff.SuffixDiffs[0].Suffix != 65 { + t.Fatalf("invalid suffix diff value found for BLOCKHASH contract at block #2: %d != 65", stemStateDiff.SuffixDiffs[0].Suffix) + } + if stemStateDiff.SuffixDiffs[0].NewValue == nil { + t.Fatalf("missing post state value for BLOCKHASH contract at block #2") + } + if *stemStateDiff.SuffixDiffs[0].NewValue != common.HexToHash("0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54") { + t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: 0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54 != %x", (*stemStateDiff.SuffixDiffs[0].NewValue)[:]) + } + } else if suffixDiff.Suffix > 4 { + t.Fatalf("invalid suffix diff found for %x in block #2: %d\n", stemStateDiff.Stem, suffixDiff.Suffix) + } + } + } +} + +func verkleTestGenesis(config *params.ChainConfig) *Genesis { + var ( + coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") + account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e") + account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d") + ) + return &Genesis{ + Config: config, + Alloc: GenesisAlloc{ + coinbase: GenesisAccount{ + Balance: big.NewInt(1000000000000000000), // 1 ether + Nonce: 0, + }, + account1: GenesisAccount{ + Balance: big.NewInt(1000000000000000000), // 1 ether + Nonce: 0, + }, + account2: GenesisAccount{ + Balance: big.NewInt(1000000000000000000), // 1 ether + Nonce: 3, + }, + params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0}, + params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0}, + params.WithdrawalQueueAddress: {Nonce: 1, Code: params.WithdrawalQueueCode, Balance: common.Big0}, + params.ConsolidationQueueAddress: {Nonce: 1, Code: params.ConsolidationQueueCode, Balance: common.Big0}, + }, + } +} + +// TestProcessVerkleContractWithEmptyCode checks that the witness contains all valid +// entries, if the initcode returns an empty code. +func TestProcessVerkleContractWithEmptyCode(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + gspec := verkleTestGenesis(&config) + + _, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) { + gen.SetPoS() + var tx types.Transaction + // a transaction that does some PUSH1n but returns a 0-sized contract + txpayload := common.Hex2Bytes("02f8db83010f2d03843b9aca008444cf6a05830186a08080b8807fdfbbb59f2371a76485ce557fd0de00c298d3ede52a3eab56d35af674eb49ec5860335260826053536001605453604c60555360f3605653606060575360446058536096605953600c605a5360df605b5360f3605c5360fb605d53600c605e53609a605f53607f60605360fe606153603d60625360f4606353604b60645360cac001a0486b6dc55b8a311568b7239a2cae1d77e7446dba71df61eaafd53f73820a138fa010bd48a45e56133ac4c5645142c2ea48950d40eb35050e9510b6bad9e15c5865") + if err := tx.UnmarshalBinary(txpayload); err != nil { + t.Fatal(err) + } + gen.AddTx(&tx) + }) + + eip2935Stem := utils.GetTreeKey(params.HistoryStorageAddress[:], uint256.NewInt(0), 0) + eip2935Stem = eip2935Stem[:31] + + for _, stemStateDiff := range statediffs[0] { + // Handle the case of the history contract: make sure only the correct + // slots are added to the witness. + if bytes.Equal(stemStateDiff.Stem[:], eip2935Stem) { + // BLOCKHASH contract stem + if len(stemStateDiff.SuffixDiffs) > 1 { + t.Fatalf("invalid suffix diff count found for BLOCKHASH contract: %d != 1", len(stemStateDiff.SuffixDiffs)) + } + if stemStateDiff.SuffixDiffs[0].Suffix != 64 { + t.Fatalf("invalid suffix diff value found for BLOCKHASH contract: %d != 64", stemStateDiff.SuffixDiffs[0].Suffix) + } + // check that the "current value" is nil and that the new value isn't. + if stemStateDiff.SuffixDiffs[0].CurrentValue != nil { + t.Fatalf("non-nil current value in BLOCKHASH contract insert: %x", stemStateDiff.SuffixDiffs[0].CurrentValue) + } + if stemStateDiff.SuffixDiffs[0].NewValue == nil { + t.Fatalf("nil new value in BLOCKHASH contract insert") + } + if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() { + t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash()) + } + } else { + for _, suffixDiff := range stemStateDiff.SuffixDiffs { + if suffixDiff.Suffix > 2 { + // if d8898012c484fb48610ecb7963886339207dab004bce968b007b616ffa18e0 shows up, it means that the PUSHn + // in the transaction above added entries into the witness, when they should not have since they are + // part of a contract deployment. + t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix) + } + } + } + } +} + +// TestProcessVerkleExtCodeHashOpcode verifies that calling EXTCODEHASH on another +// deployed contract, creates all the right entries in the witness. +func TestProcessVerkleExtCodeHashOpcode(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + gspec = verkleTestGenesis(&config) + ) + dummyContract := []byte{ + byte(vm.PUSH1), 2, + byte(vm.PUSH1), 12, + byte(vm.PUSH1), 0x00, + byte(vm.CODECOPY), + + byte(vm.PUSH1), 2, + byte(vm.PUSH1), 0x00, + byte(vm.RETURN), + + byte(vm.PUSH1), 42, + } + deployer := crypto.PubkeyToAddress(testKey.PublicKey) + dummyContractAddr := crypto.CreateAddress(deployer, 0) + + // contract that calls EXTCODEHASH on the dummy contract + extCodeHashContract := []byte{ + byte(vm.PUSH1), 22, + byte(vm.PUSH1), 12, + byte(vm.PUSH1), 0x00, + byte(vm.CODECOPY), + + byte(vm.PUSH1), 22, + byte(vm.PUSH1), 0x00, + byte(vm.RETURN), + + byte(vm.PUSH20), + 0x3a, 0x22, 0x0f, 0x35, 0x12, 0x52, 0x08, 0x9d, 0x38, 0x5b, 0x29, 0xbe, 0xca, 0x14, 0xe2, 0x7f, 0x20, 0x4c, 0x29, 0x6a, + byte(vm.EXTCODEHASH), + } + extCodeHashContractAddr := crypto.CreateAddress(deployer, 1) + + _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { + gen.SetPoS() + + if i == 0 { + // Create dummy contract. + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(0), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: dummyContract, + }) + gen.AddTx(tx) + + // Create contract with EXTCODEHASH opcode. + tx, _ = types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 1, + Value: big.NewInt(0), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: extCodeHashContract}) + gen.AddTx(tx) + } else { + tx, _ := types.SignTx(types.NewTransaction(2, extCodeHashContractAddr, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + } + }) + + contractKeccakTreeKey := utils.CodeHashKey(dummyContractAddr[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[1] { + if bytes.Equal(stemStateDiff.Stem[:], contractKeccakTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + codeHashStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0] + // Check location of code hash was accessed + if codeHashStateDiff.Suffix != utils.CodeHashLeafKey { + t.Fatalf("code hash invalid suffix") + } + // check the code hash wasn't present in the prestate, as + // the contract was deployed in this block. + if codeHashStateDiff.CurrentValue == nil { + t.Fatalf("codeHash.CurrentValue must not be empty") + } + // check the poststate value corresponds to the code hash + // of the deployed contract. + expCodeHash := crypto.Keccak256Hash(dummyContract[12:]) + if *codeHashStateDiff.CurrentValue != expCodeHash { + t.Fatalf("codeHash.CurrentValue unexpected code hash") + } + if codeHashStateDiff.NewValue != nil { + t.Fatalf("codeHash.NewValue must be nil") + } +} + +// TestProcessVerkleBalanceOpcode checks that calling balance +// on another contract will add the correct entries to the witness. +func TestProcessVerkleBalanceOpcode(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d") + gspec = verkleTestGenesis(&config) + ) + _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) { + gen.SetPoS() + txData := slices.Concat( + []byte{byte(vm.PUSH20)}, + common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d").Bytes(), + []byte{byte(vm.BALANCE)}) + + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(0), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: txData}) + gen.AddTx(tx) + }) + + account2BalanceTreeKey := utils.BasicDataKey(account2[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[0] { + if bytes.Equal(stemStateDiff.Stem[:], account2BalanceTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + var zero [32]byte + balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatalf("invalid suffix diff") + } + // check the prestate balance wasn't 0 or missing + if balanceStateDiff.CurrentValue == nil || *balanceStateDiff.CurrentValue == zero { + t.Fatalf("invalid current value %v", *balanceStateDiff.CurrentValue) + } + // check that the poststate witness value for the balance is nil, + // meaning that it didn't get updated. + if balanceStateDiff.NewValue != nil { + t.Fatalf("invalid new value") + } +} + +// TestProcessVerkleSelfDestructInSeparateTx controls the contents of the witness after +// a non-eip6780-compliant selfdestruct occurs. +func TestProcessVerkleSelfDestructInSeparateTx(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d") + gspec = verkleTestGenesis(&config) + ) + + // runtime code: selfdestruct ( 0x6177843db3138ae69679A54b95cf345ED759450d ) + runtimeCode := slices.Concat( + []byte{byte(vm.PUSH20)}, + account2.Bytes(), + []byte{byte(vm.SELFDESTRUCT)}) + + //The goal of this test is to test SELFDESTRUCT that happens in a contract + // execution which is created in a previous transaction. + selfDestructContract := slices.Concat([]byte{ + byte(vm.PUSH1), byte(len(runtimeCode)), + byte(vm.PUSH1), 12, + byte(vm.PUSH1), 0x00, + byte(vm.CODECOPY), // Codecopy( to-offset: 0, code offset: 12, length: 22 ) + + byte(vm.PUSH1), byte(len(runtimeCode)), + byte(vm.PUSH1), 0x00, + byte(vm.RETURN), // Return ( 0 : len(runtimecode) + }, + runtimeCode) + + deployer := crypto.PubkeyToAddress(testKey.PublicKey) + contract := crypto.CreateAddress(deployer, 0) + + _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { + gen.SetPoS() + + if i == 0 { + // Create selfdestruct contract, sending 42 wei. + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(42), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: selfDestructContract, + }) + gen.AddTx(tx) + } else { + // Call it. + tx, _ := types.SignTx(types.NewTransaction(1, contract, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + } + }) + + var zero [32]byte + { // Check self-destructed contract in the witness + selfDestructContractTreeKey := utils.CodeHashKey(contract[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[1] { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatalf("balance invalid suffix") + } + + // The original balance was 42. + var oldBalance [16]byte + oldBalance[15] = 42 + if !bytes.Equal((*balanceStateDiff.CurrentValue)[utils.BasicDataBalanceOffset:], oldBalance[:]) { + t.Fatalf("the pre-state balance before self-destruct must be %x, got %x", oldBalance, *balanceStateDiff.CurrentValue) + } + + // The new balance must be 0. + if !bytes.Equal((*balanceStateDiff.NewValue)[utils.BasicDataBalanceOffset:], zero[utils.BasicDataBalanceOffset:]) { + t.Fatalf("the post-state balance after self-destruct must be 0") + } + } + { // Check self-destructed target in the witness. + selfDestructTargetTreeKey := utils.CodeHashKey(account2[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[1] { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructTargetTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatalf("balance invalid suffix") + } + if balanceStateDiff.CurrentValue == nil { + t.Fatalf("codeHash.CurrentValue must not be empty") + } + if balanceStateDiff.NewValue == nil { + t.Fatalf("codeHash.NewValue must not be empty") + } + preStateBalance := binary.BigEndian.Uint64(balanceStateDiff.CurrentValue[utils.BasicDataBalanceOffset+8:]) + postStateBalance := binary.BigEndian.Uint64(balanceStateDiff.NewValue[utils.BasicDataBalanceOffset+8:]) + if postStateBalance-preStateBalance != 42 { + t.Fatalf("the post-state balance after self-destruct must be 42, got %d-%d=%d", postStateBalance, preStateBalance, postStateBalance-preStateBalance) + } + } +} + +// TestProcessVerkleSelfDestructInSeparateTx controls the contents of the witness after +// a eip6780-compliant selfdestruct occurs. +func TestProcessVerkleSelfDestructInSameTx(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d") + gspec = verkleTestGenesis(&config) + ) + + // The goal of this test is to test SELFDESTRUCT that happens in a contract + // execution which is created in **the same** transaction sending the remaining + // balance to an external (i.e: not itself) account. + + selfDestructContract := slices.Concat( + []byte{byte(vm.PUSH20)}, + account2.Bytes(), + []byte{byte(vm.SELFDESTRUCT)}) + deployer := crypto.PubkeyToAddress(testKey.PublicKey) + contract := crypto.CreateAddress(deployer, 0) + + _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) { + gen.SetPoS() + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(42), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: selfDestructContract, + }) + gen.AddTx(tx) + }) + + { // Check self-destructed contract in the witness + selfDestructContractTreeKey := utils.CodeHashKey(contract[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[0] { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatalf("balance invalid suffix") + } + + if balanceStateDiff.CurrentValue != nil { + t.Fatalf("the pre-state balance before must be nil, since the contract didn't exist") + } + + if balanceStateDiff.NewValue != nil { + t.Fatalf("the post-state balance after self-destruct must be nil since the contract shouldn't be created at all") + } + } + { // Check self-destructed target in the witness. + selfDestructTargetTreeKey := utils.CodeHashKey(account2[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[0] { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructTargetTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatalf("no state diff found for stem") + } + + balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatalf("balance invalid suffix") + } + if balanceStateDiff.CurrentValue == nil { + t.Fatalf("codeHash.CurrentValue must not be empty") + } + if balanceStateDiff.NewValue == nil { + t.Fatalf("codeHash.NewValue must not be empty") + } + preStateBalance := binary.BigEndian.Uint64(balanceStateDiff.CurrentValue[utils.BasicDataBalanceOffset+8:]) + postStateBalance := binary.BigEndian.Uint64(balanceStateDiff.NewValue[utils.BasicDataBalanceOffset+8:]) + if postStateBalance-preStateBalance != 42 { + t.Fatalf("the post-state balance after self-destruct must be 42. got %d", postStateBalance) + } + } +} + +// TestProcessVerkleSelfDestructInSeparateTxWithSelfBeneficiary checks the content of the witness +// if a selfdestruct occurs in a different tx than the one that created it, but the beneficiary +// is the selfdestructed account. +func TestProcessVerkleSelfDestructInSeparateTxWithSelfBeneficiary(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + gspec = verkleTestGenesis(&config) + ) + // The goal of this test is to test SELFDESTRUCT that happens in a contract + // execution which is created in a *previous* transaction sending the remaining + // balance to itself. + selfDestructContract := []byte{ + byte(vm.PUSH1), 2, // PUSH1 2 + byte(vm.PUSH1), 10, // PUSH1 12 + byte(vm.PUSH0), // PUSH0 + byte(vm.CODECOPY), // Codecopy ( to offset 0, code@offset: 10, length: 2) + + byte(vm.PUSH1), 22, + byte(vm.PUSH0), + byte(vm.RETURN), // RETURN( memory[0:2] ) + + // Deployed code + byte(vm.ADDRESS), + byte(vm.SELFDESTRUCT), + } + deployer := crypto.PubkeyToAddress(testKey.PublicKey) + contract := crypto.CreateAddress(deployer, 0) + + _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { + gen.SetPoS() + if i == 0 { + // Create self-destruct contract, sending 42 wei. + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(42), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: selfDestructContract, + }) + gen.AddTx(tx) + } else { + // Call it. + tx, _ := types.SignTx(types.NewTransaction(1, contract, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey) + gen.AddTx(tx) + } + }) + + { + // Check self-destructed contract in the witness. + // The way 6780 is implemented today, it always SubBalance from the self-destructed contract, and AddBalance + // to the beneficiary. In this case both addresses are the same, thus this might be optimizable from a gas + // perspective. But until that happens, we need to honor this "balance reading" adding it to the witness. + + selfDestructContractTreeKey := utils.CodeHashKey(contract[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range statediffs[1] { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatal("no state diff found for stem") + } + + balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatal("balance invalid suffix") + } + + // The original balance was 42. + var oldBalance [16]byte + oldBalance[15] = 42 + if !bytes.Equal((*balanceStateDiff.CurrentValue)[utils.BasicDataBalanceOffset:], oldBalance[:]) { + t.Fatal("the pre-state balance before self-destruct must be 42") + } + + // Note that the SubBalance+AddBalance net effect is a 0 change, so NewValue + // must be nil. + if balanceStateDiff.NewValue != nil { + t.Fatal("the post-state balance after self-destruct must be empty") + } + } +} + +// TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiary checks the content of the witness +// if a selfdestruct occurs in the same tx as the one that created it, but the beneficiary +// is the selfdestructed account. +func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiary(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + gspec = verkleTestGenesis(&config) + deployer = crypto.PubkeyToAddress(testKey.PublicKey) + contract = crypto.CreateAddress(deployer, 0) + ) + + // The goal of this test is to test SELFDESTRUCT that happens while executing + // the init code of a contract creation, that occurs in **the same** transaction. + // The balance is sent to itself. + t.Logf("Contract: %v", contract.String()) + + selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)} + + _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) { + gen.SetPoS() + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(42), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: selfDestructContract, + }) + gen.AddTx(tx) + }) + stateDiff := stateDiffs[0] // state difference of block 1 + + { // Check self-destructed contract in the witness + selfDestructContractTreeKey := utils.CodeHashKey(contract[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range stateDiff { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatal("no state diff found for stem") + } + balanceStateDiff := stateDiff[stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatal("balance invalid suffix") + } + if balanceStateDiff.CurrentValue != nil { + t.Fatal("the pre-state balance before must be nil, since the contract didn't exist") + } + // Ensure that the value is burnt, and therefore that the balance of the self-destructed + // contract isn't modified (it should remain missing from the state) + if balanceStateDiff.NewValue != nil { + t.Fatal("the post-state balance after self-destruct must be nil since the contract shouldn't be created at all") + } + } +} + +// TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiaryAndPrefundedAccount checks the +// content of the witness if a selfdestruct occurs in the same tx as the one that created it, +// it, but the beneficiary is the selfdestructed account. The difference with the test above, +// is that the created account is prefunded and so the final value should be 0. +func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiaryAndPrefundedAccount(t *testing.T) { + // The test txs were taken from a secondary testnet with chain id 69421 + config := *testKaustinenLikeChainConfig + config.ChainID.SetUint64(69421) + + var ( + signer = types.LatestSigner(&config) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + gspec = verkleTestGenesis(&config) + deployer = crypto.PubkeyToAddress(testKey.PublicKey) + contract = crypto.CreateAddress(deployer, 0) + ) + // Prefund the account, at an address that the contract will be deployed at, + // before it selfdestrucs. We can therefore check that the account itseld is + // NOT destroyed, which is what the currrent version of the spec requires. + // TODO(gballet) revisit after the spec has been modified. + gspec.Alloc[contract] = types.Account{ + Balance: big.NewInt(100), + } + + selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)} + + _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) { + gen.SetPoS() + tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0, + Value: big.NewInt(42), + Gas: 100_000, + GasPrice: big.NewInt(875000000), + Data: selfDestructContract, + }) + gen.AddTx(tx) + }) + stateDiff := stateDiffs[0] // state difference of block 1 + + { // Check self-destructed contract in the witness + selfDestructContractTreeKey := utils.CodeHashKey(contract[:]) + + var stateDiffIdx = -1 + for i, stemStateDiff := range stateDiff { + if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) { + stateDiffIdx = i + break + } + } + if stateDiffIdx == -1 { + t.Fatal("no state diff found for stem") + } + balanceStateDiff := stateDiff[stateDiffIdx].SuffixDiffs[0] + if balanceStateDiff.Suffix != utils.BasicDataLeafKey { + t.Fatal("balance invalid suffix") + } + expected, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000064") + if balanceStateDiff.CurrentValue == nil || !bytes.Equal(balanceStateDiff.CurrentValue[:], expected) { + t.Fatalf("incorrect prestate balance: %x != %x", *balanceStateDiff.CurrentValue, expected) + } + // Ensure that the value is burnt, and therefore that the balance of the self-destructed + // contract isn't modified (it should remain missing from the state) + expected = make([]byte, 32) + if balanceStateDiff.NewValue == nil { + t.Fatal("incorrect nil poststate balance") + } + if !bytes.Equal(balanceStateDiff.NewValue[:], expected[:]) { + t.Fatalf("incorrect poststate balance: %x != %x", *balanceStateDiff.NewValue, expected[:]) + } + } +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 26ff495579..0593a32a3e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -213,9 +213,6 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. code := evm.StateDB.GetCode(addr) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(code) - } if len(code) == 0 { ret, err = nil, nil // gas is unchanged } else { @@ -283,9 +280,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(caller.Address()), value, gas) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas @@ -333,9 +327,6 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by addrCopy := addr // Initialise a new contract and make initialise the delegate values contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas @@ -391,9 +382,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) - if witness := evm.StateDB.Witness(); witness != nil { - witness.AddCode(evm.StateDB.GetCode(addrCopy)) - } contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 540f0e508d..dc7bf18683 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -340,10 +340,6 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.peek() - address := slot.Bytes20() - if witness := interpreter.evm.StateDB.Witness(); witness != nil { - witness.AddCode(interpreter.evm.StateDB.GetCode(address)) - } slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20()))) return nil, nil } @@ -383,9 +379,6 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) } addr := common.Address(a.Bytes20()) code := interpreter.evm.StateDB.GetCode(addr) - if witness := interpreter.evm.StateDB.Witness(); witness != nil { - witness.AddCode(code) - } codeCopy := getData(code, uint64CodeOffset, length.Uint64()) scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) @@ -987,13 +980,13 @@ func makePush(size uint64, pushByteSize int) executionFunc { start = min(codeLen, int(*pc+1)) end = min(codeLen, start+pushByteSize) ) - scope.Stack.push(new(uint256.Int).SetBytes( - common.RightPadBytes( - scope.Contract.Code[start:end], - pushByteSize, - )), - ) + a := new(uint256.Int).SetBytes(scope.Contract.Code[start:end]) + // Missing bytes: pushByteSize - len(pushData) + if missing := pushByteSize - (end - start); missing > 0 { + a.Lsh(a, uint(8*missing)) + } + scope.Stack.push(a) *pc += size return nil, nil } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index a3f9ee81d1..b8e62e1de5 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -927,3 +927,75 @@ func TestOpMCopy(t *testing.T) { } } } + +// TestPush sanity-checks how code with immediates are handled when the code size is +// smaller than the size of the immediate. +func TestPush(t *testing.T) { + code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121") + + push32 := makePush(32, 32) + + scope := &ScopeContext{ + Memory: nil, + Stack: newstack(), + Contract: &Contract{ + Code: code, + }, + } + for i, want := range []string{ + "0x11223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1", + "0x223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1", + "0x3344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1", + "0x44556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1", + "0x556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1", + "0x6677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1", + "0x77889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191", + "0x889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181", + "0x9900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171", + "0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161", + "0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151", + "0xbbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141", + "0xccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131", + "0xddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121", + "0xeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100", + "0xff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000", + "0x102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000", + "0x2030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000", + "0x30405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000", + "0x405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000", + "0x5060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000", + "0x60708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000", + "0x708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000", + "0x8090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000", + "0x90a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000", + "0xa0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000000000", + "0xb0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000000000", + "0xc0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000000000", + "0xd0e0ff1e1d1c1b1a19181716151413121000000000000000000000000000000", + "0xe0ff1e1d1c1b1a1918171615141312100000000000000000000000000000000", + "0xff1e1d1c1b1a191817161514131210000000000000000000000000000000000", + "0xf1e1d1c1b1a19181716151413121000000000000000000000000000000000000", + "0xe1d1c1b1a1918171615141312100000000000000000000000000000000000000", + "0xd1c1b1a191817161514131210000000000000000000000000000000000000000", + "0xc1b1a19181716151413121000000000000000000000000000000000000000000", + "0xb1a1918171615141312100000000000000000000000000000000000000000000", + "0xa191817161514131210000000000000000000000000000000000000000000000", + "0x9181716151413121000000000000000000000000000000000000000000000000", + "0x8171615141312100000000000000000000000000000000000000000000000000", + "0x7161514131210000000000000000000000000000000000000000000000000000", + "0x6151413121000000000000000000000000000000000000000000000000000000", + "0x5141312100000000000000000000000000000000000000000000000000000000", + "0x4131210000000000000000000000000000000000000000000000000000000000", + "0x3121000000000000000000000000000000000000000000000000000000000000", + "0x2100000000000000000000000000000000000000000000000000000000000000", + "0x0", + } { + pc := new(uint64) + *pc = uint64(i) + push32(pc, nil, scope) + res := scope.Stack.pop() + if have := res.Hex(); have != want { + t.Fatalf("case %d, have %v want %v", i, have, want) + } + } +} diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 793f398367..c408994401 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -249,8 +249,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } else if sLen > operation.maxStack { return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} } - if !contract.UseGas(cost, in.evm.Config.Tracer, tracing.GasChangeIgnored) { + // for tracing: this gas consumption event is emitted below in the debug section. + if contract.Gas < cost { return nil, ErrOutOfGas + } else { + contract.Gas -= cost } if operation.dynamicGas != nil { @@ -279,8 +282,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( if err != nil { return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err) } - if !contract.UseGas(dynamicCost, in.evm.Config.Tracer, tracing.GasChangeIgnored) { + // for tracing: this gas consumption event is emitted below in the debug section. + if contract.Gas < dynamicCost { return nil, ErrOutOfGas + } else { + contract.Gas -= dynamicCost } // Do tracing before memory expansion diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 2ad991ee41..2243e14b65 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -142,13 +142,16 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { // set the receiver's (the executing contract) code for execution. cfg.State.SetCode(address, code) // Call the code with the given configuration. - ret, _, err := vmenv.Call( + ret, leftOverGas, err := vmenv.Call( sender, common.BytesToAddress([]byte("contract")), input, cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return ret, cfg.State, err } @@ -181,6 +184,9 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return code, address, leftOverGas, err } @@ -214,5 +220,8 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er cfg.GasLimit, uint256.MustFromBig(cfg.Value), ) + if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil { + cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err) + } return ret, leftOverGas, err } diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 1aefc810bd..97234368ee 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -514,6 +514,17 @@ func BenchmarkSimpleLoop(b *testing.B) { byte(vm.JUMP), } + loopingCode2 := []byte{ + byte(vm.JUMPDEST), // [ count ] + // push args for the call + byte(vm.PUSH4), 1, 2, 3, 4, + byte(vm.PUSH5), 1, 2, 3, 4, 5, + + byte(vm.POP), byte(vm.POP), + byte(vm.PUSH6), 0, 0, 0, 0, 0, 0, // jumpdestination + byte(vm.JUMP), + } + callRevertingContractWithInput := []byte{ byte(vm.JUMPDEST), // // push args for the call @@ -540,6 +551,7 @@ func BenchmarkSimpleLoop(b *testing.B) { benchmarkNonModifyingCode(100000000, staticCallIdentity, "staticcall-identity-100M", "", b) benchmarkNonModifyingCode(100000000, callIdentity, "call-identity-100M", "", b) benchmarkNonModifyingCode(100000000, loopingCode, "loop-100M", "", b) + benchmarkNonModifyingCode(100000000, loopingCode2, "loop2-100M", "", b) benchmarkNonModifyingCode(100000000, callInexistant, "call-nonexist-100M", "", b) benchmarkNonModifyingCode(100000000, callEOA, "call-EOA-100M", "", b) benchmarkNonModifyingCode(100000000, callRevertingContractWithInput, "call-reverting-100M", "", b) diff --git a/docs/postmortems/2021-08-22-split-postmortem.md b/docs/postmortems/2021-08-22-split-postmortem.md index 5ec4f37e87..2e5c41c764 100644 --- a/docs/postmortems/2021-08-22-split-postmortem.md +++ b/docs/postmortems/2021-08-22-split-postmortem.md @@ -56,7 +56,7 @@ On the evening of 17th, we discussed options on how to handle it. We made a stat It was decided that in this specific instance, it would be possible to make a public announcement and a patch release: - The fix can be made pretty 'generically', e.g. always copying data on input to precompiles. -- The flaw is pretty difficult to find, given a generic fix in the call. The attacker needs to figure out that it concerns the precompiles, specifically the datcopy, and that it concerns the `RETURNDATA` buffer rather than the regular memory, and lastly the special circumstances to trigger it (overlapping but shifted input/output). +- The flaw is pretty difficult to find, given a generic fix in the call. The attacker needs to figure out that it concerns the precompiles, specifically the datacopy, and that it concerns the `RETURNDATA` buffer rather than the regular memory, and lastly the special circumstances to trigger it (overlapping but shifted input/output). Since we had merged the removal of `ETH65`, if the entire network were to upgrade, then nodes which have not yet implemented `ETH66` would be cut off from the network. After further discussions, we decided to: diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 7bb31329c6..3ac719c23e 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -208,7 +208,6 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { t.Fatalf("error preparing payload, err=%v", err) } // give the payload some time to be built - time.Sleep(100 * time.Millisecond) payloadID := (&miner.BuildPayloadArgs{ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, @@ -217,12 +216,12 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { BeaconRoot: blockParams.BeaconRoot, Version: engine.PayloadV1, }).Id() - execData, err := api.GetPayloadV1(payloadID) + execData, err := api.getPayload(payloadID, true) if err != nil { t.Fatalf("error getting payload, err=%v", err) } - if len(execData.Transactions) != blocks[9].Transactions().Len() { - t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions)) + if len(execData.ExecutionPayload.Transactions) != blocks[9].Transactions().Len() { + t.Fatalf("invalid number of transactions %d != 1", len(execData.ExecutionPayload.Transactions)) } // Test invalid payloadID var invPayload engine.PayloadID @@ -453,7 +452,6 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) } mcfg := miner.DefaultConfig - mcfg.PendingFeeRecipient = testAddr ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg} ethservice, err := eth.New(n, ethcfg) if err != nil { @@ -628,7 +626,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { SafeBlockHash: common.Hash{}, FinalizedBlockHash: common.Hash{}, } - payload *engine.ExecutableData + payload *engine.ExecutionPayloadEnvelope resp engine.ForkChoiceResponse err error ) @@ -640,11 +638,10 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status) } // give the payload some time to be built - time.Sleep(50 * time.Millisecond) - if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil { + if payload, err = api.getPayload(*resp.PayloadID, true); err != nil { t.Fatalf("can't get payload: %v", err) } - if len(payload.Transactions) > 0 { + if len(payload.ExecutionPayload.Transactions) > 0 { break } // No luck this time we need to update the params and try again. @@ -653,7 +650,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("payload should not be empty") } } - execResp, err := api.NewPayloadV1(*payload) + execResp, err := api.NewPayloadV1(*payload.ExecutionPayload) if err != nil { t.Fatalf("can't execute payload: %v", err) } @@ -661,14 +658,14 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { t.Fatalf("invalid status: %v", execResp.Status) } fcState = engine.ForkchoiceStateV1{ - HeadBlockHash: payload.BlockHash, - SafeBlockHash: payload.ParentHash, - FinalizedBlockHash: payload.ParentHash, + HeadBlockHash: payload.ExecutionPayload.BlockHash, + SafeBlockHash: payload.ExecutionPayload.ParentHash, + FinalizedBlockHash: payload.ExecutionPayload.ParentHash, } if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.ExecutionPayload.Number { t.Fatalf("Chain head should be updated") } parent = ethservice.BlockChain().CurrentBlock() @@ -1736,9 +1733,6 @@ func TestWitnessCreationAndConsumption(t *testing.T) { if err != nil { t.Fatalf("error preparing payload, err=%v", err) } - // Give the payload some time to be built - time.Sleep(100 * time.Millisecond) - payloadID := (&miner.BuildPayloadArgs{ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, @@ -1748,7 +1742,7 @@ func TestWitnessCreationAndConsumption(t *testing.T) { BeaconRoot: blockParams.BeaconRoot, Version: engine.PayloadV3, }).Id() - envelope, err := api.GetPayloadV3(payloadID) + envelope, err := api.getPayload(payloadID, true) if err != nil { t.Fatalf("error getting payload, err=%v", err) } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index c325e5010c..f1a815e6d3 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -138,9 +138,6 @@ type Config struct { VMTrace string VMTraceJsonConfig string - // Miscellaneous options - DocRoot string `toml:"-"` - // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap uint64 diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index d96ba0ccb7..0ec0eaddeb 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -46,7 +46,6 @@ func (c Config) MarshalTOML() (interface{}, error) { EnablePreimageRecording bool VMTrace string VMTraceJsonConfig string - DocRoot string `toml:"-"` RPCGasCap uint64 RPCEVMTimeout time.Duration RPCTxFeeCap float64 @@ -83,7 +82,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.EnablePreimageRecording = c.EnablePreimageRecording enc.VMTrace = c.VMTrace enc.VMTraceJsonConfig = c.VMTraceJsonConfig - enc.DocRoot = c.DocRoot enc.RPCGasCap = c.RPCGasCap enc.RPCEVMTimeout = c.RPCEVMTimeout enc.RPCTxFeeCap = c.RPCTxFeeCap @@ -124,7 +122,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { EnablePreimageRecording *bool VMTrace *string VMTraceJsonConfig *string - DocRoot *string `toml:"-"` RPCGasCap *uint64 RPCEVMTimeout *time.Duration RPCTxFeeCap *float64 @@ -222,9 +219,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.VMTraceJsonConfig != nil { c.VMTraceJsonConfig = *dec.VMTraceJsonConfig } - if dec.DocRoot != nil { - c.DocRoot = *dec.DocRoot - } if dec.RPCGasCap != nil { c.RPCGasCap = *dec.RPCGasCap } diff --git a/eth/filters/bench_test.go b/eth/filters/bench_test.go deleted file mode 100644 index 73b96b77af..0000000000 --- a/eth/filters/bench_test.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package filters - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/bitutil" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/node" -) - -func BenchmarkBloomBits512(b *testing.B) { - benchmarkBloomBits(b, 512) -} - -func BenchmarkBloomBits1k(b *testing.B) { - benchmarkBloomBits(b, 1024) -} - -func BenchmarkBloomBits2k(b *testing.B) { - benchmarkBloomBits(b, 2048) -} - -func BenchmarkBloomBits4k(b *testing.B) { - benchmarkBloomBits(b, 4096) -} - -func BenchmarkBloomBits8k(b *testing.B) { - benchmarkBloomBits(b, 8192) -} - -func BenchmarkBloomBits16k(b *testing.B) { - benchmarkBloomBits(b, 16384) -} - -func BenchmarkBloomBits32k(b *testing.B) { - benchmarkBloomBits(b, 32768) -} - -const benchFilterCnt = 2000 - -func benchmarkBloomBits(b *testing.B, sectionSize uint64) { - b.Skip("test disabled: this tests presume (and modify) an existing datadir.") - benchDataDir := node.DefaultDataDir() + "/geth/chaindata" - b.Log("Running bloombits benchmark section size:", sectionSize) - - db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", benchDataDir, err) - } - head := rawdb.ReadHeadBlockHash(db) - if head == (common.Hash{}) { - b.Fatalf("chain data not found at %v", benchDataDir) - } - - clearBloomBits(db) - b.Log("Generating bloombits data...") - headNum := rawdb.ReadHeaderNumber(db, head) - if headNum == nil || *headNum < sectionSize+512 { - b.Fatalf("not enough blocks for running a benchmark") - } - - start := time.Now() - cnt := (*headNum - 512) / sectionSize - var dataSize, compSize uint64 - for sectionIdx := uint64(0); sectionIdx < cnt; sectionIdx++ { - bc, err := bloombits.NewGenerator(uint(sectionSize)) - if err != nil { - b.Fatalf("failed to create generator: %v", err) - } - var header *types.Header - for i := sectionIdx * sectionSize; i < (sectionIdx+1)*sectionSize; i++ { - hash := rawdb.ReadCanonicalHash(db, i) - if header = rawdb.ReadHeader(db, hash, i); header == nil { - b.Fatalf("Error creating bloomBits data") - return - } - bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom) - } - sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*sectionSize-1) - for i := 0; i < types.BloomBitLength; i++ { - data, err := bc.Bitset(uint(i)) - if err != nil { - b.Fatalf("failed to retrieve bitset: %v", err) - } - comp := bitutil.CompressBytes(data) - dataSize += uint64(len(data)) - compSize += uint64(len(comp)) - rawdb.WriteBloomBits(db, uint(i), sectionIdx, sectionHead, comp) - } - //if sectionIdx%50 == 0 { - // b.Log(" section", sectionIdx, "/", cnt) - //} - } - - d := time.Since(start) - b.Log("Finished generating bloombits data") - b.Log(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") - b.Log(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) - - b.Log("Running filter benchmarks...") - start = time.Now() - - var ( - backend *testBackend - sys *FilterSystem - ) - for i := 0; i < benchFilterCnt; i++ { - if i%20 == 0 { - db.Close() - db, _ = rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - backend = &testBackend{db: db, sections: cnt} - sys = NewFilterSystem(backend, Config{}) - } - var addr common.Address - addr[0] = byte(i) - addr[1] = byte(i / 256) - filter := sys.NewRangeFilter(0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) - if _, err := filter.Logs(context.Background()); err != nil { - b.Error("filter.Logs error:", err) - } - } - - d = time.Since(start) - b.Log("Finished running filter benchmarks") - b.Log(" ", d, "total ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks") - db.Close() -} - -//nolint:unused -func clearBloomBits(db ethdb.Database) { - var bloomBitsPrefix = []byte("bloomBits-") - fmt.Println("Clearing bloombits data...") - it := db.NewIterator(bloomBitsPrefix, nil) - for it.Next() { - db.Delete(it.Key()) - } - it.Release() -} - -func BenchmarkNoBloomBits(b *testing.B) { - b.Skip("test disabled: this tests presume (and modify) an existing datadir.") - benchDataDir := node.DefaultDataDir() + "/geth/chaindata" - b.Log("Running benchmark without bloombits") - db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", benchDataDir, err) - } - head := rawdb.ReadHeadBlockHash(db) - if head == (common.Hash{}) { - b.Fatalf("chain data not found at %v", benchDataDir) - } - headNum := rawdb.ReadHeaderNumber(db, head) - - clearBloomBits(db) - - _, sys := newTestFilterSystem(b, db, Config{}) - - b.Log("Running filter benchmarks...") - start := time.Now() - filter := sys.NewRangeFilter(0, int64(*headNum), []common.Address{{}}, nil) - filter.Logs(context.Background()) - d := time.Since(start) - b.Log("Finished running filter benchmarks") - b.Log(" ", d, "total ", d*time.Duration(1000000)/time.Duration(*headNum+1), "per million blocks") - db.Close() -} diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index d8b703fee4..6a3057326d 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -48,7 +48,7 @@ func makeReceipt(addr common.Address) *types.Receipt { func BenchmarkFilters(b *testing.B) { var ( - db, _ = rawdb.NewLevelDBDatabase(b.TempDir(), 0, 0, "", false) + db = rawdb.NewMemoryDatabase() _, sys = newTestFilterSystem(b, db, Config{}) key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index faf360cc53..d0509f2f3d 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -17,10 +17,12 @@ package eth import ( + "bytes" "math" "math/big" "math/rand" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" @@ -37,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" ) var ( @@ -142,10 +145,12 @@ func (b *testBackend) RunPeer(peer *Peer, handler Handler) error { func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") } func (b *testBackend) AcceptTxs() bool { - panic("data processing tests should be done in the handler package") + return true + //panic("data processing tests should be done in the handler package") } func (b *testBackend) Handle(*Peer, Packet) error { - panic("data processing tests should be done in the handler package") + return nil + //panic("data processing tests should be done in the handler package") } // Tests that block headers can be retrieved from a remote chain based on user queries. @@ -498,3 +503,76 @@ func testGetBlockReceipts(t *testing.T, protocol uint) { t.Errorf("receipts mismatch: %v", err) } } + +type decoder struct { + msg []byte +} + +func (d decoder) Decode(val interface{}) error { + buffer := bytes.NewBuffer(d.msg) + s := rlp.NewStream(buffer, uint64(len(d.msg))) + return s.Decode(val) +} + +func (d decoder) Time() time.Time { + return time.Now() +} + +func setup() (*testBackend, *testPeer) { + // Generate some transactions etc. + acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") + acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") + acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) + acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) + signer := types.HomesteadSigner{} + gen := func(n int, block *core.BlockGen) { + if n%2 == 0 { + w := &types.Withdrawal{ + Address: common.Address{0xaa}, + Amount: 42, + } + block.AddWithdrawal(w) + } + switch n { + case 0: + // In block 1, the test bank sends account #1 some ether. + tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) + block.AddTx(tx) + case 1: + // In block 2, the test bank sends some more ether to account #1. + // acc1Addr passes it on to account #2. + tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) + tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key) + block.AddTx(tx1) + block.AddTx(tx2) + case 2: + // Block 3 is empty but was mined by account #2. + block.SetCoinbase(acc2Addr) + block.SetExtra([]byte("yeehaw")) + } + } + backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen) + peer, _ := newTestPeer("peer", ETH68, backend) + // Discard all messages + go func() { + for { + msg, err := peer.app.ReadMsg() + if err == nil { + msg.Discard() + } + } + }() + return backend, peer +} + +func FuzzEthProtocolHandlers(f *testing.F) { + handlers := eth68 + backend, peer := setup() + f.Fuzz(func(t *testing.T, code byte, msg []byte) { + handler := handlers[uint64(code)%protocolLengths[ETH68]] + if handler == nil { + return + } + handler(backend, decoder{msg: msg}, peer.Peer) + }) +} diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 5b9c809596..cb635e7127 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/tests" ) @@ -202,7 +201,7 @@ func BenchmarkTracers(b *testing.B) { func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { // Configure a blockchain with the given prestate tx := new(types.Transaction) - if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { + if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil { b.Fatalf("failed to parse testcase input: %v", err) } signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) @@ -211,15 +210,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { Origin: origin, GasPrice: tx.GasPrice(), } - context := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: test.Context.Miner, - BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: uint64(test.Context.Time), - Difficulty: (*big.Int)(test.Context.Difficulty), - GasLimit: uint64(test.Context.GasLimit), - } + context := test.Context.toBlockContext(test.Genesis) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json index 26495dfbce..7acb221666 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json @@ -44,6 +44,7 @@ "result": [ { "action": { + "creationMethod": "create", "from": "0xf8bda96b67036ee48107f2a0695ea673479dda56", "gas": "0x231860", "init": "0x5b620186a05a131560135760016020526000565b600080601f600039601f565b6000f3", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json index 72a4db6901..a098b57029 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x19f78", @@ -66,8 +67,7 @@ "transactionPosition": 74, "transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4", "blockNumber": 1555279, - "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46", - "time": "209.346µs" + "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46" }, { "action": { diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json index 0c4d29dd5b..6baa57689f 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x1a758", @@ -66,8 +67,7 @@ "transactionPosition": 141, "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", "blockNumber": 1555278, - "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", - "time": "300.9µs" + "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b" }, { "type": "call", @@ -80,9 +80,7 @@ "callType": "callcode" }, "error": "out of gas", - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 141, "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", @@ -90,4 +88,4 @@ "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json index 5538a708ea..8949dcfe57 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x1a034", @@ -62,8 +63,7 @@ "transactionPosition": 117, "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "332.877µs" + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" }, { "type": "call", @@ -76,9 +76,7 @@ "callType": "callcode" }, "error": "invalid input length", - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 117, "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", @@ -86,4 +84,4 @@ "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json index 83d20fb078..2de8f8d4d5 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json @@ -47,6 +47,7 @@ "result": [ { "action": { + "creationMethod": "create", "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", "gas": "0x897be", "init": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json new file mode 100644 index 0000000000..5e79e6ad45 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create_oog_parity.json @@ -0,0 +1,94 @@ +{ + "genesis": { + "difficulty": "4639933", + "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", + "gasLimit": "9280188", + "hash": "0x9a5f3a98eb1c60f6e3f450658a9cea190157e7021d04f927b752ad6482cf9194", + "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", + "mixHash": "0x6b6f8fcaa54b8565c4c1ae7cf0a020e938a53007f4561e758b17bc05c9044d78", + "nonce": "0x773aba50dc51b462", + "number": "1555169", + "stateRoot": "0xc4b9703de3e59ff795baae2c3afa010cf039c37244a7a6af7f3f491a10601348", + "timestamp": "1590794111", + "totalDifficulty": "2242105342155", + "alloc": { + "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x62325b40cbbd0915c4b9", + "nonce": "260875", + "code": "0x", + "storage": {} + } + }, + "config": { + "chainId": 63, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 0, + "eip158Block": 0, + "ethash": {}, + "homesteadBlock": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 301243, + "petersburgBlock": 999983, + "istanbulBlock": 999983 + } + }, + "context": { + "number": "1555170", + "difficulty": "4642198", + "timestamp": "1590794112", + "gasLimit": "9289249", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf8658303fb0b843b9aca0083019ee48080915a600055600060006000f0505a6001550081a2a01a7deb3a16d967b766459ef486b00656c6581e5ad58968184a33701e27e0eb8aa07162ccdfe2018d64360a605310a62c399dd586c7282dd42a88c54f02f51d451f", + "tracerConfig": { + "convertParityErrors": true + }, + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0x19ee4", + "init": "0x5a600055600060006000f0505a60015500", + "creationMethod": "create" + }, + "error": "Out of gas", + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 63, + "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", + "blockNumber": 1555170, + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" + }, + { + "type": "create", + "action": { + "from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8", + "value": "0x0", + "gas": "0x3cb", + "init": "0x", + "creationMethod": "create" + }, + "result": { + "gasUsed": "0x0", + "code": "0x", + "address": "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d" + }, + "traceAddress": [0], + "subtraces": 0, + "transactionPosition": 63, + "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", + "blockNumber": 1555170, + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json index 250c402808..2fad32afe2 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x1a9c8", @@ -66,8 +67,7 @@ "transactionPosition": 18, "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "453.925µs" + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" }, { "type": "call", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json index 3747d7f0f8..0af816e683 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json @@ -71,6 +71,7 @@ }, { "action": { + "creationMethod": "create", "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", "gas": "0x39ff0", "init": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json index 7dc6cc8098..4383af2d8a 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x53e90", @@ -66,12 +67,12 @@ "transactionPosition": 23, "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", "blockNumber": 555462, - "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1", - "time": "1.147715ms" + "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1" }, { "type": "create", "action": { + "creationMethod": "create", "from": "0x9db7a1baf185a865ffee3824946ccd8958191e5e", "value": "0x0", "gas": "0x30b34", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json index 82692d181a..9fe9ba2b9d 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x19ed8", @@ -66,12 +67,12 @@ "transactionPosition": 31, "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", "blockNumber": 1555161, - "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171", - "time": "889.048µs" + "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171" }, { "type": "create", "action": { + "creationMethod": "create2", "from": "0x2e8eded627eead210cb6143eb39ef7a3e44e4f00", "value": "0x0", "gas": "0x5117", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json index d9595a7210..f8ad3b5b0e 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x19ee4", @@ -62,12 +63,12 @@ "transactionPosition": 63, "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", "blockNumber": 1555170, - "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e", - "time": "952.736µs" + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" }, { "type": "create", "action": { + "creationMethod": "create", "from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8", "value": "0x0", "gas": "0x3cb", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json index cb4954d9b7..41199e90e3 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json @@ -73,11 +73,11 @@ "transactionPosition": 26, "transactionHash": "0xcb1090fa85d2a3da8326b75333e92b3dca89963c895d9c981bfdaa64643135e4", "blockNumber": 839247, - "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c", - "time": "182.267µs" + "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c" }, { "action": { + "creationMethod": "create", "from": "0x76554b33410b6d90b7dc889bfed0451ad195f27e", "gas": "0x25a18", "init": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -90,4 +90,4 @@ "type": "create" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json index b8b20e1b8c..a7421d294d 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json @@ -96,6 +96,7 @@ "result": [ { "action": { + "creationMethod": "create", "from": "0x5409ed021d9299bf6814279a6a1411a7e866a631", "gas": "0x2c8c7f", "init": "0x60806040523480156200001157600080fd5b5060405162002d2c38038062002d2c83398101806040526200003791908101906200051d565b6000805433600160a060020a031991821617825560018054909116600160a060020a0386161790558251849084908490849081906200007e906004906020870190620003d0565b50825162000094906005906020860190620003d0565b50620000b0836010640100000000620019476200036f82021704565b9150620000cd846010640100000000620019476200036f82021704565b60028054600160a060020a03948516600160a060020a031991821617909155600380549285169290911691909117905550600154604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130181207f6070410800000000000000000000000000000000000000000000000000000000825291909216945063607041089350620001739250906004016200068e565b602060405180830381600087803b1580156200018e57600080fd5b505af1158015620001a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001c99190810190620004f4565b9050600160a060020a038116151562000219576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021090620006b0565b60405180910390fd5b6002546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b39062000268908490600019906004016200066f565b602060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002be9190810190620005a1565b506003546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b3906200030e908490600019906004016200066f565b602060405180830381600087803b1580156200032957600080fd5b505af11580156200033e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003649190810190620005a1565b50505050506200077a565b600081601401835110151515620003b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000210906200069e565b506014818301810151910190600160a060020a03165b92915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200041357805160ff191683800117855562000443565b8280016001018555821562000443579182015b828111156200044357825182559160200191906001019062000426565b506200045192915062000455565b5090565b6200047291905b808211156200045157600081556001016200045c565b90565b600062000483825162000711565b9392505050565b600062000483825162000742565b6000601f82018313620004aa57600080fd5b8151620004c1620004bb82620006e9565b620006c2565b91508082526020830160208301858383011115620004de57600080fd5b620004eb83828462000747565b50505092915050565b6000602082840312156200050757600080fd5b600062000515848462000475565b949350505050565b6000806000606084860312156200053357600080fd5b600062000541868662000475565b93505060208401516001604060020a038111156200055e57600080fd5b6200056c8682870162000498565b92505060408401516001604060020a038111156200058957600080fd5b620005978682870162000498565b9150509250925092565b600060208284031215620005b457600080fd5b60006200051584846200048a565b620005cd8162000711565b82525050565b620005cd816200071d565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601881527f554e524547495354455245445f41535345545f50524f58590000000000000000602082015260400190565b620005cd8162000472565b604081016200067f8285620005c2565b62000483602083018462000664565b60208101620003ca8284620005d3565b60208082528101620003ca81620005de565b60208082528101620003ca8162000634565b6040518181016001604060020a0381118282101715620006e157600080fd5b604052919050565b60006001604060020a038211156200070057600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b151590565b60005b83811015620007645781810151838201526020016200074a565b8381111562000774576000848401525b50505050565b6125a2806200078a6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf5003700000000000000000000000048bacb9266a570d521063ef5dd96e61686dbe788000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e808200000000000000000000000000000000000000000000000000000000", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json index f6215a2b3f..544fff9dd3 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json @@ -80,8 +80,7 @@ "transactionPosition": 5, "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", "blockNumber": 553416, - "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282", - "time": "617.42µs" + "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" }, { "type": "call", @@ -97,9 +96,7 @@ "gasUsed": "0x0", "output": "0x" }, - "traceAddress": [ - 0 - ], + "traceAddress": [0], "subtraces": 0, "transactionPosition": 5, "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", @@ -107,4 +104,4 @@ "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json index c8c6dc65c1..d7b4a22cf5 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x19ecc", @@ -66,11 +67,11 @@ "transactionPosition": 14, "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", "blockNumber": 1555146, - "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e", - "time": "187.145µs" + "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e" }, { "action": { + "creationMethod": "create", "from": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca", "gas": "0x50ac", "init": "0x5a", @@ -90,9 +91,7 @@ "balance": "0x0" }, "result": null, - "traceAddress": [ - 1 - ], + "traceAddress": [1], "subtraces": 0, "transactionPosition": 14, "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", @@ -100,4 +99,4 @@ "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json index a25f2383d6..6e020fe2b7 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json @@ -51,6 +51,7 @@ { "type": "create", "action": { + "creationMethod": "create", "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", "value": "0x0", "gas": "0x1aab0", @@ -62,11 +63,11 @@ "transactionPosition": 16, "transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05", "blockNumber": 1555285, - "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f", - "time": "665.278µs" + "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f" }, { "action": { + "creationMethod": "create", "from": "0xf84bf5189ccd19f5897739756d214fa0dc099e0d", "gas": "0x1d5c", "init": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", @@ -79,4 +80,4 @@ "type": "create" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json new file mode 100644 index 0000000000..d60c3d7385 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json @@ -0,0 +1,83 @@ +{ + "context": { + "difficulty": "3502894804", + "gasLimit": "4722976", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2289806", + "timestamp": "1513601314" + }, + "genesis": { + "alloc": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "code": "0x", + "nonce": "22", + "storage": {} + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "code": "0x", + "nonce": "29072", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "eip150Block": 0, + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3509749784", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4727564", + "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", + "nonce": "0x4eb12e19c16d43da", + "number": "2289805", + "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", + "timestamp": "1513601261", + "totalDifficulty": "7143276353481064" + }, + "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", + "tracerConfig": { + "disableCode": true + }, + "result": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "nonce": 22 + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "nonce": 1, + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "nonce": 29072 + }, + "0x1585936b53834b021f68cc13eeefdec2efc8e724": { + "balance": "0x0" + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json new file mode 100644 index 0000000000..b37dfa90a1 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json @@ -0,0 +1,78 @@ +{ + "context": { + "difficulty": "3502894804", + "gasLimit": "4722976", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2289806", + "timestamp": "1513601314" + }, + "genesis": { + "alloc": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "code": "0x", + "nonce": "22", + "storage": {} + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "code": "0x", + "nonce": "29072", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "eip150Block": 0, + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3509749784", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4727564", + "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", + "nonce": "0x4eb12e19c16d43da", + "number": "2289805", + "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", + "timestamp": "1513601261", + "totalDifficulty": "7143276353481064" + }, + "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", + "tracerConfig": { + "disableCode": true, + "disableStorage": true + }, + "result": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "nonce": 22 + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "nonce": 1 + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "nonce": 29072 + }, + "0x1585936b53834b021f68cc13eeefdec2efc8e724": { + "balance": "0x0" + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json new file mode 100644 index 0000000000..43d6e03b44 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json @@ -0,0 +1,78 @@ +{ + "context": { + "difficulty": "3502894804", + "gasLimit": "4722976", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2289806", + "timestamp": "1513601314" + }, + "genesis": { + "alloc": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "code": "0x", + "nonce": "22", + "storage": {} + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "code": "0x", + "nonce": "29072", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "eip150Block": 0, + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3509749784", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4727564", + "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", + "nonce": "0x4eb12e19c16d43da", + "number": "2289805", + "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", + "timestamp": "1513601261", + "totalDifficulty": "7143276353481064" + }, + "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", + "tracerConfig": { + "disableStorage": true + }, + "result": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "nonce": 22 + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "nonce": 1, + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029" + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "nonce": 29072 + }, + "0x1585936b53834b021f68cc13eeefdec2efc8e724": { + "balance": "0x0" + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_code.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_code.json new file mode 100644 index 0000000000..5d7c024a5e --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_code.json @@ -0,0 +1,100 @@ +{ + "genesis": { + "difficulty": "13756228101629", + "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", + "gasLimit": "3141592", + "hash": "0x58b7a87b6ba10b46b4e251d64ebc3d9822dd82218eaf24dff6796f6f1f687251", + "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", + "mixHash": "0x5984b9a316116bd890e6e5f4c52d655184b0d7aa74821e1382d7760f9803c1dd", + "nonce": "0xea4bb4997242c681", + "number": "1061221", + "stateRoot": "0x5402c04d481414248d824c3b61e924e0c9307adbc9fbaae774a74cce30a4163d", + "timestamp": "1456458069", + "totalDifficulty": "7930751135586064334", + "alloc": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb6b81e112638b886", + "nonce": "217865", + "code": "0x" + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b6828e22bb12188", + "nonce": "747", + "code": "0x" + } + }, + "config": { + "chainId": 1, + "homesteadBlock": 1150000, + "daoForkBlock": 1920000, + "eip150Block": 2463000, + "eip155Block": 2675000, + "eip158Block": 2675000, + "byzantiumBlock": 4370000, + "constantinopleBlock": 7280000, + "petersburgBlock": 7280000, + "istanbulBlock": 9069000, + "muirGlacierBlock": 9200000, + "berlinBlock": 12244000, + "londonBlock": 12965000, + "arrowGlacierBlock": 13773000, + "grayGlacierBlock": 15050000, + "ethash": {} + } + }, + "context": { + "number": "1061222", + "difficulty": "13749511193633", + "timestamp": "1456458097", + "gasLimit": "3141592", + "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" + }, + "input": "0xf905498202eb850ba43b7400830f42408080b904f460606040526040516102b43803806102b48339016040526060805160600190602001505b5b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b806001600050908051906020019082805482825590600052602060002090601f01602090048101928215609e579182015b82811115609d5782518260005055916020019190600101906081565b5b50905060c5919060a9565b8082111560c1576000818150600090555060010160a9565b5090565b50505b506101dc806100d86000396000f30060606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001ee7b225f6964223a225a473466784a7245323639384866623839222c22666f726d5f736f75726365223a22434c54523031222c22636f6d6d69746d656e745f64617465223a22222c22626f72726f7765725f6e616d65223a22222c22626f72726f7765725f616464726573735f6c696e6531223a22222c22626f72726f7765725f616464726573735f6c696e6532223a22222c22626f72726f7765725f636f6e74616374223a22222c22626f72726f7765725f7374617465223a22222c22626f72726f7765725f74797065223a22222c2270726f70657274795f61646472657373223a22222c226c6f616e5f616d6f756e745f7772697474656e223a22222c226c6f616e5f616d6f756e74223a22222c224c54565f7772697474656e223a22222c224c5456223a22222c2244534352223a22222c2270726f70657274795f74797065223a22222c2270726f70657274795f6465736372697074696f6e223a22222c226c656e646572223a22222c2267756172616e746f7273223a22222c226c696d69746564223a22222c226361705f616d6f756e74223a22222c226361705f70657263656e745f7772697474656e223a22222c226361705f70657263656e74616765223a22222c227465726d5f7772697474656e223a22222c227465726d223a22222c22657874656e64223a22227d0000000000000000000000000000000000001ba027d54712289af34f0ec0f06092745104d68e5801cd17097bc1104111f855258da070ec9f1c942d9bedf89f9660a684d3bb8cd9c2ac7f6dd883cb3e26a193180244", + "tracerConfig": { + "diffMode": true, + "disableCode": true + }, + "result": { + "pre": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb6b81e112638b886", + "nonce": 217865 + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b6828e22bb12188", + "nonce": 747 + } + }, + "post": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb71abdd2621d8886" + }, + "0x40f2f445da6c9047554683fb382fba6769717116": { + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f0c5cef39b17c213cfe090a46b8c7760ffb7928a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000000000000000001ee", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "0x7b225f6964223a225a473466784a7245323639384866623839222c22666f726d", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7": "0x5f736f75726365223a22434c54523031222c22636f6d6d69746d656e745f6461", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8": "0x7465223a22222c22626f72726f7765725f6e616d65223a22222c22626f72726f", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9": "0x7765725f616464726573735f6c696e6531223a22222c22626f72726f7765725f", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa": "0x616464726573735f6c696e6532223a22222c22626f72726f7765725f636f6e74", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb": "0x616374223a22222c22626f72726f7765725f7374617465223a22222c22626f72", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfc": "0x726f7765725f74797065223a22222c2270726f70657274795f61646472657373", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfd": "0x223a22222c226c6f616e5f616d6f756e745f7772697474656e223a22222c226c", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfe": "0x6f616e5f616d6f756e74223a22222c224c54565f7772697474656e223a22222c", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cff": "0x224c5456223a22222c2244534352223a22222c2270726f70657274795f747970", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d00": "0x65223a22222c2270726f70657274795f6465736372697074696f6e223a22222c", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d01": "0x226c656e646572223a22222c2267756172616e746f7273223a22222c226c696d", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d02": "0x69746564223a22222c226361705f616d6f756e74223a22222c226361705f7065", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d03": "0x7263656e745f7772697474656e223a22222c226361705f70657263656e746167", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d04": "0x65223a22222c227465726d5f7772697474656e223a22222c227465726d223a22", + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d05": "0x222c22657874656e64223a22227d000000000000000000000000000000000000" + } + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b058920efcc5188", + "nonce": 748 + } + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_storage.json new file mode 100644 index 0000000000..65594feb44 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_disable_storage.json @@ -0,0 +1,81 @@ +{ + "genesis": { + "difficulty": "13756228101629", + "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", + "gasLimit": "3141592", + "hash": "0x58b7a87b6ba10b46b4e251d64ebc3d9822dd82218eaf24dff6796f6f1f687251", + "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", + "mixHash": "0x5984b9a316116bd890e6e5f4c52d655184b0d7aa74821e1382d7760f9803c1dd", + "nonce": "0xea4bb4997242c681", + "number": "1061221", + "stateRoot": "0x5402c04d481414248d824c3b61e924e0c9307adbc9fbaae774a74cce30a4163d", + "timestamp": "1456458069", + "totalDifficulty": "7930751135586064334", + "alloc": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb6b81e112638b886", + "nonce": "217865", + "code": "0x" + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b6828e22bb12188", + "nonce": "747", + "code": "0x" + } + }, + "config": { + "chainId": 1, + "homesteadBlock": 1150000, + "daoForkBlock": 1920000, + "eip150Block": 2463000, + "eip155Block": 2675000, + "eip158Block": 2675000, + "byzantiumBlock": 4370000, + "constantinopleBlock": 7280000, + "petersburgBlock": 7280000, + "istanbulBlock": 9069000, + "muirGlacierBlock": 9200000, + "berlinBlock": 12244000, + "londonBlock": 12965000, + "arrowGlacierBlock": 13773000, + "grayGlacierBlock": 15050000, + "ethash": {} + } + }, + "context": { + "number": "1061222", + "difficulty": "13749511193633", + "timestamp": "1456458097", + "gasLimit": "3141592", + "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" + }, + "input": "0xf905498202eb850ba43b7400830f42408080b904f460606040526040516102b43803806102b48339016040526060805160600190602001505b5b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b806001600050908051906020019082805482825590600052602060002090601f01602090048101928215609e579182015b82811115609d5782518260005055916020019190600101906081565b5b50905060c5919060a9565b8082111560c1576000818150600090555060010160a9565b5090565b50505b506101dc806100d86000396000f30060606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001ee7b225f6964223a225a473466784a7245323639384866623839222c22666f726d5f736f75726365223a22434c54523031222c22636f6d6d69746d656e745f64617465223a22222c22626f72726f7765725f6e616d65223a22222c22626f72726f7765725f616464726573735f6c696e6531223a22222c22626f72726f7765725f616464726573735f6c696e6532223a22222c22626f72726f7765725f636f6e74616374223a22222c22626f72726f7765725f7374617465223a22222c22626f72726f7765725f74797065223a22222c2270726f70657274795f61646472657373223a22222c226c6f616e5f616d6f756e745f7772697474656e223a22222c226c6f616e5f616d6f756e74223a22222c224c54565f7772697474656e223a22222c224c5456223a22222c2244534352223a22222c2270726f70657274795f74797065223a22222c2270726f70657274795f6465736372697074696f6e223a22222c226c656e646572223a22222c2267756172616e746f7273223a22222c226c696d69746564223a22222c226361705f616d6f756e74223a22222c226361705f70657263656e745f7772697474656e223a22222c226361705f70657263656e74616765223a22222c227465726d5f7772697474656e223a22222c227465726d223a22222c22657874656e64223a22227d0000000000000000000000000000000000001ba027d54712289af34f0ec0f06092745104d68e5801cd17097bc1104111f855258da070ec9f1c942d9bedf89f9660a684d3bb8cd9c2ac7f6dd883cb3e26a193180244", + "tracerConfig": { + "diffMode": true, + "disableStorage": true + }, + "result": { + "pre": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb6b81e112638b886", + "nonce": 217865 + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b6828e22bb12188", + "nonce": 747 + } + }, + "post": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x9fb71abdd2621d8886" + }, + "0x40f2f445da6c9047554683fb382fba6769717116": { + "code": "0x60606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056" + }, + "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { + "balance": "0x15b058920efcc5188", + "nonce": 748 + } + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create_disable_code_and_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create_disable_code_and_storage.json new file mode 100644 index 0000000000..96c93e7cf8 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create_disable_code_and_storage.json @@ -0,0 +1,256 @@ +{ + "genesis": { + "difficulty": "13707196986889", + "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", + "gasLimit": "3141592", + "hash": "0x607b38fe7e94427ee8f3b9a62375c67f953f8d49e05dbfd0145f9d3bac142193", + "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", + "mixHash": "0x98c74c9e76fd0078157e1696e4334a7e787396459693a84536d8b96414dafd5d", + "nonce": "0x77a5a0a73ad8745e", + "number": "1062502", + "stateRoot": "0x1df615df5fdbc8d5397bf3574f462f6d9696428eb8796d8e9252bccc8e3a8996", + "timestamp": "1456480432", + "totalDifficulty": "7948153536501153741", + "alloc": { + "0x0000000000000000000000000000000000000004": { + "balance": "0x0", + "code": "0x" + }, + "0x1deeda36e15ec9e80f3d7414d67a4803ae45fc80": { + "balance": "0x0", + "code": "0x650200d2f18c7350606060405236156100c15760e060020a60003504630bd295e681146100c65780630fd1f94e1461017d5780630fee183d1461018c578063349501b7146101ad5780635054d98a146101c75780637c0278fc146101ef5780637e92656214610287578063a0943154146102f6578063a1873db61461030e578063a9d2293d14610355578063b5d0f16e146103ad578063c17e6817146103ce578063cc3471af1461046a578063da46be0a1461047a578063f55627531461052a575b610007565b6105d36004356024356044355b60006000600030915081600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515191505080841080610173575081600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015060ff16810184115b1561100d57610007565b6105d3600060f0610f6d61046e565b6105d3600435602435604435606435600081600202831015610ff657610fee565b6105d36004355b600081600014156109115750600161098f565b6105d36004355b6008810154600090819062010000900460ff16156105f257600691506105ec565b60408051602060248035600481810135601f81018590048502860185019096528585526105e5958135959194604494929390920191819084018382808284375094965050505050505060006004825103836001016000508181546001816001161561010002031660029004825481601f106108005782601f1061083a575b826008026101000360020a80910402828001178355610851565b6105e5600435602435604051600090600160a060020a038316907f398bd6b21ae4164ec322fb0eb8c2eb6277f36fd41903fbbed594dfe125591281908390a26007830154819010610e415760078301546005840154610e3f9162010000909104600160a060020a0316906103d8565b6105d3600435602435600060006000611064856101ce565b6105d36004356024356044356004830154600090819030908410156110e4577f4e4f545f454e4f5547485f47415300000000000000000000000000000000000091506112dd565b6105d35b60006000309050600a81600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515160091901935050505b5090565b6105d36004356024355b60008282111561099e578183606402049050610998565b6105d36004356024355b600030600160a060020a0316318211156103fa57600160a060020a0330163191505b6000821115610994577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc84846040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100075750839250610998915050565b6105d35b6000600f610f6d610359565b6105e560043560243560443560643560843560088501805461ff00191661010017905584543090600090819081908190819060a060020a900460e060020a02811480156104db575060018b8101546002918116156101000260001901160481145b156109b3578a5460028c0154600160a060020a039190911690895a60405191900391906000818181858888f193505050508b60080160006101000a81548160ff02191690830217905550610bfa565b6105d36004355b6000600060006000309250600a83600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151600919019350505081851115610eb05782600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450610ea89050565b60408051918252519081900360200190f35b005b600291505b50919050565b6008830154610100900460ff161561060d57600591506105ec565b30905080600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515143610109011015905061066457600091506105ec565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515143600a01101590506106d3576005830154620100009004600160a060020a0316600014156105e757600191506105ec565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151431015905061072357600391506105ec565b80600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015060ff1681600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519190910143101590506107bf57600491506105ec565b600791506105ec565b5081800160010183558181151161085157601f016020900481601f016020900483600052602060002091820191016108519190610826565b82601f106107c8575082600052602060002080549082601f016020900481019061090691905b808211156103a95760008155600101610826565b60ff19168360005260206000205581800160010183555b5050505060048251111561090c575060005b6001838101546002918116156101000260001901160481101561090c57818160040181518110156100075790602001015160f860020a900460f860020a02836001016000508281546001816001161561010002031660029004811015610007578154600116156108e25790600052602060002090602091828204019190065b601f036101000a81548160ff0219169060f860020a84040217905550600101610863565b5061026d565b505050565b604080517f5f5f6469672875696e74323536290000000000000000000000000000000000008152815190819003600e01812060e060020a9081900481028190049081028252600019850160048301529151600160a060020a03301692916102bc86029160248281019260009291908290030181838887f19450505050505b919050565b5060005b92915050565b818360020203836064020460c8039050610998565b8a5460a060020a900460e060020a0260001415610a23578a5460028c0154600160a060020a039190911690895a03908d6001016000506040518082805460018160011615610100020316600290048015610ae55780601f10610aba57610100808354040283529160200191610ae5565b60018b8101546002918116156101000260001901160460001415610b1a578a5460028c0154600160a060020a039190911690895a03908d60000160149054906101000a900460e060020a0260e060020a900491906040518360e060020a028152600401809050600060405180830381858988f19450505050508b60080160006101000a81548160ff02191690830217905550610bfa565b820191906000526020600020905b815481529060010190602001808311610ac857829003601f168201915b5050915050600060405180830381858888f193505050508b60080160006101000a81548160ff02191690830217905550610bfa565b8a5460028c0154600160a060020a039190911690895a03908d60000160149054906101000a900460e060020a0260e060020a900491908e6001016000506040518460e060020a0281526004018082805460018160011615610100020316600290048015610bc85780601f10610b9d57610100808354040283529160200191610bc8565b820191906000526020600020905b815481529060010190602001808311610bab57829003601f168201915b5050915050600060405180830381858988f19450505050508b60080160006101000a81548160ff021916908302179055505b85600160a060020a031663938b5f326040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750505060405180519060200150600160a060020a031660405180807f75706461746544656661756c745061796d656e742829000000000000000000008152602001506016019050604051809103902060e060020a8091040260e060020a90046040518160e060020a0281526004018090506000604051808303816000876161da5a03f15050505060038b0154610cc8903a6103b7565b60058c0154909550620100009004600160a060020a03908116908a161415610cf65760068b01549350610d38565b85600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450505b6064858502048b6007016000505401925060648587600160a060020a031663625cc4656040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505050604051805190602001500204915060008b60070160005081905550865a8b03013a029050610db7898285016103d8565b9250610dd773d3cda913deb6f67967b99d67acdfa1712c293601836103d8565b6040805160088e01548482526020820187905281830184905260ff1660608201529051919350600160a060020a038b16917f4538b7ec91dae8fada01e66a052482086d3e690c3db5a80457fbcd55457b4ae19181900360800190a25050505050505050505050565b505b309050610e8c81600160a060020a031663ae45850b6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515190316103d8565b505050600801805462ff0000191662010000179055565b600093505b505050919050565b600e19919091019081851115610f075782600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450610ea89050565b60ef19919091019081851115610ea357818503905060f08184600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015002049350610ea8565b03905090565b6006860181905560058601805475ffffffffffffffffffffffffffffffffffffffff000019166201000087021790556007860184905560408051600160a060020a0387168152602081019290925280517fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9281900390910190a15b949350505050565b610f7343610531565b600192505b50509392505050565b60108185031015610fff576005860154620100009004600160a060020a03166000148061105057506005860154620100009004600160a060020a03908116908616145b9250611004565b600092505b505092915050565b91503090506000821480156110c4575080600160a060020a031663ae45850b6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151600160a060020a039081169086161490505b156110d2576001925061105c565b6007821415611057576001925061105c565b6008860154610100900460ff161561111e577f414c52454144595f43414c4c454400000000000000000000000000000000000091506112dd565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051514310905080611206575080600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040805180517f0a16697a000000000000000000000000000000000000000000000000000000008252915160ff9092169291630a16697a9160048181019260209290919082900301816000876161da5a03f1156100075750506040515191909101431190505b15611233577f4e4f545f494e5f43414c4c5f57494e444f57000000000000000000000000000091506112dd565b61123e8686436100d3565b151561126c577f4e4f545f415554484f52495a454400000000000000000000000000000000000091506112dd565b6005860154600061ffff91909116118015611299575032600160a060020a031685600160a060020a031614155b80156112b4575060058601546112b29061ffff166101b4565b155b156112dd577f535441434b5f544f4f5f4445455000000000000000000000000000000000000091505b60008214610fff5760408051600160a060020a03871681526020810184905281517fdcb278834ca505ad219cf8e4b5d11f026080abef6ec68e249ea5e4d9bb3dc7b2929181900390910190a16000925061100456" + }, + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x98e1c608601c2496b2", + "nonce": "218916", + "code": "0x" + }, + "0x651913977e8140c323997fce5e03c19e0015eebf": { + "balance": "0x0", + "code": "0x", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { + "balance": "0x0", + "nonce": "237", + "code": "0x6060604052361561027c5760e060020a600035046301991313811461027e57806303d22885146102ca5780630450991814610323578063049ae734146103705780630ce46c43146103c35780630e85023914610602578063112e39a8146106755780631b4fa6ab146106c25780631e74a2d3146106d057806326a7985a146106fd5780633017fe2414610753578063346cabbc1461075c578063373a1bc3146107d55780633a9e74331461081e5780633c2c21a01461086e5780633d9ce89b146108ba578063480b70bd1461092f578063481078431461097e57806348f0518714610a0e5780634c471cde14610a865780634db3da8314610b09578063523ccfa814610b4f578063586a69fa14610be05780635a9f2def14610c3657806364ee49fe14610caf57806367beaccb14610d055780636840246014610d74578063795b9a6f14610dca5780637b55c8b514610e415780637c73f84614610ee15780638c0e156d14610f145780638c1d01c814610f605780638e46afa914610f69578063938c430714610fc0578063971c803f146111555780639772c982146111ac57806398c9cdf41461122857806398e00e541461127f5780639f927be7146112d5578063a00aede914611383578063a1c0539d146113d3578063aff21c6514611449578063b152f19e14611474578063b549793d146114cb578063b5b33eda1461154b578063bbc6eb1f1461159b578063c0f68859146115ab578063c3a2c0c314611601578063c43d05751461164b578063d8e5c04814611694578063dbfef71014611228578063e29fb547146116e7578063e6470fbe1461173a578063ea27a8811461174c578063ee77fe86146117d1578063f158458c14611851575b005b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387876020604051908101604052806000815260200150612225610f6d565b61188260043560243560443560643560843560a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338b8a6020604051908101604052806000815260200150896125196106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a026020604051908101604052806000815260200150611e4a610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503389896020604051908101604052806000815260200150886124e86106c6565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750506040805160a08082019092529597963596608435969095506101449450925060a491506005908390839080828437509095505050505050604080518082018252600160a060020a03338116825288166020820152815160c0810190925260009173e54d323f9ef17c1f0dede47ecc86a9718fe5ea349163e3042c0f91600191908a908a9089908b90808b8b9090602002015181526020018b60016005811015610002579090602002015181526020018b60026005811015610002579090602002015181526020018b60036005811015610002579090602002015181526020018b6004600581101561000257909060200201518152602001348152602001506040518860e060020a02815260040180888152602001876002602002808383829060006004602084601f0104600f02600301f150905001868152602001806020018560ff1681526020018461ffff168152602001836006602002808383829060006004602084601f0104600f02600301f1509050018281038252868181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d25780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038160008760325a03f2156100025750506040515191506124cd9050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808787611e64610f6d565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611d28610f6d565b61189f5b6000611bf8611159565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881600060005054611a9561159f565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346326a7985a6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b760075b90565b604080516020606435600481810135601f8101849004840285018401909552848452611882948135946024803595604435956084949201919081908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160013389898861224b610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386866020604051908101604052806000815260200150611e64610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333896020604051908101604052806000815260200150886123bc6106c6565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387866020604051908101604052806000815260200150611f8d610f6d565b60408051602060248035600481810135601f810185900485028601850190965285855261188295813595919460449492939092019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808888612225610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503388886020604051908101604052806000815260200150612388610f6d565b611882600435604080517fc4144b2600000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163c4144b26916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133888888612238610f6d565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338b8b8b896126536106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333866020604051908101604052806000815260200150611e4a610f6d565b6118b76004355b604080517fed5bd7ea00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163ed5bd7ea916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b61189f600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463586a69fa6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650509335935050606435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808989612388610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a896020604051908101604052806000815260200150886124d76106c6565b6040805160206004803580820135601f8101849004840285018401909552848452611882949193602493909291840191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808587611e4a610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a8a60206040519081016040528060008152602001508961262d6106c6565b604080516020606435600481810135601f810184900484028501840190955284845261188294813594602480359560443595608494920191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338888876120c7610f6d565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437505060408051608080820190925295979635969561010495509350608492508591508390839080828437509095505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989898961263a6106c6565b6118b7600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881858585611ba361122c565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050333388602060405190810160405280600081526020015061236e610f6d565b6118b760005481565b6118c95b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea34638e46afa96040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a43560c43560e43561010435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338e8e8d8f8e8e8e8e8e346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156111195780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519b9a5050505050505050505050565b61189f5b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463971c803f6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650509335935050608435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989896123a2610f6d565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398c9cdf46040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398e00e546040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600435604080517fe6ce3a6a000000000000000000000000000000000000000000000000000000008152600160048201527f3e3d0000000000000000000000000000000000000000000000000000000000006024820152604481018390529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163e6ce3a6a916064818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a0260206040519081016040528060008152602001506121ef610f6d565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338787876120b5610f6d565b6118b7600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88183611b4561159f565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463b152f19e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808b8b8961262d6106c6565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386600060e060020a026020604051908101604052806000815260200150612200610f6d565b6118b75b60005460649004610759565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463c0f688596040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611bff610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333876020604051908101604052806000815260200150612200610f6d565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387600060e060020a026020604051908101604052806000815260200150612213610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338a60206040519081016040528060008152602001508961250c6106c6565b61027c6000600060006118e033610b56565b6118b7600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881868686866040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b949350505050565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338a8a8a886124fa6106c6565b6118b7600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88184846000611b4f61122c565b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b15611a905733925082600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fc6803622000000000000000000000000000000000000000000000000000000008252915191945063c680362291600482810192602092919082900301816000876161da5a03f11561000257505060405151905080156119d1575082600160a060020a031663d379be236040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a03166000141590505b80156119dd5750600082115b80156119ec5750600054600190115b15611a90578183600160a060020a031663830953ab6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040515160640291909104915050604281118015611a4d5750600054829011155b15611a675760008054612710612711909102049055611a90565b602181108015611a7a5750600054829010155b15611a90576000805461271061270f9091020490555b505050565b6000611a9f61122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b919050565b6000611af261122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b9392505050565b9050610759565b611c076106c6565b6000611c11611478565b611c1961122c565b600054611c2461159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611cf25780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b611d306106c6565b60008b611d3b61122c565b600054611d4661159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611e145780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b409050565b611e526106c6565b6000611e5c611478565b611d3b61122c565b611e6c6106c6565b6000611e76611478565b611e7e61122c565b600054611e8961159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611f575780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b9d9050565b611f956106c6565b8b611f9e611478565b611fa661122c565b600054611fb161159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561207f5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611bf19050565b6120bd6106c6565b6000611f9e611478565b6120cf6106c6565b8b6120d8611478565b6120e061122c565b6000546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156121b95780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506117c99050565b6121f76106c6565b8b611e76611478565b6122086106c6565b60008b611e7e61122c565b61221b6106c6565b8a8c611fa661122c565b61222d6106c6565b60008b611fa661122c565b6122406106c6565b60008b6120e061122c565b6122536106c6565b8c8b61225d61122c565b60005461226861159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156123365780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f21561000257505060405151979650505050505050565b6123766106c6565b60008c8c600060005054611fb161159f565b6123906106c6565b60008c8c6000600050546120eb61159f565b6123aa6106c6565b60008c8c60006000505461226861159f565b60008d8d6000600050546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561249c5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150505b9695505050505050565b8e8d8d6000600050546123ce61159f565b60008d8d60006000505461226861159f565b60008d8d6000600050546123ce61159f565b60008e8e8d61226861159f565b8f8e8e8d61252561159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156125f35780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519998505050505050505050565b60008e8e8d6123ce61159f565b8a5160208c015160408d015160608e015161226861159f565b60008e8e8d61252561159f56", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000011f8119429ed3a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", + "0x031b9ec274101cc3ccff4d6d98ef4513742dadbaadba538bff48b88403253234": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x20ef51bb8ea9e8e8d5e2c17d28e47285698893c1017db4b4e40b792358a3dbc7": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abd": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", + "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abf": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", + "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8ac2": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfb": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfc": "0x00000000000000000000000000000000000000000000000000000000000f6897", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfd": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfe": "0x0000000000000000000000002859ddf2877c46d54e67b6becdb1cafb8ef4a458", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dff": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", + "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794e00": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x3b20a4b931bc4ae9450774ee52b8f5da1b248d23e61cd20c09b25662f73894fd": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x3b99aee1e3090227401ac2055c861246ca6ec62f426b4b4d74df88510f841b89": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef711": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef712": "0x0000000000000000000000000000000000000000000000000000000000102ce9", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef713": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef714": "0x00000000000000000000000016917c151bb1399852a0741eb7b317b443e2cfa3", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef715": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", + "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef716": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a3fe": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a3ff": "0x00000000000000000000000000000000000000000000000000000000000fff67", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a400": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a401": "0x00000000000000000000000010fc2e8ba5f40336c3576ffaa25177f1cdedf836", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a402": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", + "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a403": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5ba": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bb": "0x000000000000000000000000000000000000000000000000000000000010347b", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bc": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bd": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5be": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", + "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bf": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2751": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2752": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2753": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2754": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2755": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2756": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a7": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a8": "0x00000000000000000000000000000000000000000000000000000000000fe13d", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a9": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826aa": "0x00000000000000000000000063110531142fb314118164ff579ba52746504408", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826ab": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", + "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826ac": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0xac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c890780": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xccd2cbc946692be8ade97db99353304e3af0fa6202f93649d4e185ad8b1f385c": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4ef": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f0": "0x00000000000000000000000000000000000000000000000000000000001030b3", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f1": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f2": "0x000000000000000000000000dd87a67740c2acf48a31829783a095a81c3628d9", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f3": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", + "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f4": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0xdabde47554d6a6cfcff3c968abb145f298585fafa9e24c10fc526269794bd626": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db7": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db8": "0x000000000000000000000000000000000000000000000000000000000010365c", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db9": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dba": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbb": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbc": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdec": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bded": "0x0000000000000000000000000000000000000000000000000000000000101dc2", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdee": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdef": "0x000000000000000000000000173243e117a6382211b1ac91eeb262f4a7021c16", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdf0": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", + "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdf1": "0x0000000000000000000000000000000000000000000000000000000000000005" + } + }, + "0x741467b251fca923d6229c4b439078b55dca233b": { + "balance": "0x29c613529e8218f8", + "code": "0x606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000007dd677b54fc954824a7bc49bd26cbdfa12c75adf", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000011f79bd42b0c7c", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000002dfeff8fca5d", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000003defb9627dd677b54fc954824a7bc49bd26cbdfa12c75adf", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000ba43b7400", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x00000000000000000000000000000000000000000000000000000000001e8480", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000006c8f2a135f6ed072de4503bd7c4999a1a17f824b", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x000000000000000000000000000000000000000000000000000000000010365c", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x00000000000000000000000000000000000000000000000000000000000000ff" + } + }, + "0x7c1eb207c07e7ab13cf245585bd03d0fa478d034": { + "balance": "0x0", + "code": "0x650200d2f18c7350606060405236156100a05760e060020a60003504630e9f1a3c81146100a55780632b4096b4146100c95780636ec13982146100eb578063a3119e571461010d578063a749f19b1461012f578063ab7366f714610151578063bacd69581461017f578063bfdf87c0146101c2578063c4144b26146101e1578063caa46c9c1461023c578063e6ce3a6a14610297578063ed5bd7ea146102b6575b610007565b6102d960043560243560008181526001830160205260409020600401545b92915050565b6102d960043560243560008181526001830160205260409020600301546100c3565b6102d960043560243560008181526001830160205260409020600201546100c3565b6102d960043560243560008181526001838101602052604090912001546100c3565b6102d960043560243560008181526001830160205260409020600501546100c3565b6102eb6004356024355b600081815260018301602052604081208054829182918291908614610790576101b9565b6102eb600435602435604435600082815260018401602052604081205481908190819086141561068a576040812060010154851415610680575b50505050505050565b6102d960043560243560008181526001830160205260409020546100c3565b6102d96004356024355b6040805160c08101825260008082526020828101829052828401829052606083018290526080830182905260a08301829052848252600186019052918220805490919083908114156102fb576102f2565b6102d96004356024355b6040805160c08101825260008082526020828101829052828401829052606083018290526080830182905260a08301829052848252600186019052918220805490919083908114156104c0576102f2565b6102d960043560243560443582546000908181811415610a6557610a8c565b6102d96004356024356000818152600183016020526040812060050154116100c3565b60408051918252519081900360200190f35b005b815193505b50505092915050565b60048301546000146103d257600483810154600090815260018881016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015460608201529181015460808301526005015460a082015291505b60608201516000146102ed57606091820151600090815260018781016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015493810193909352600481015460808401526005015460a0830152610364565b600283015460001461045b5750506002810154600081815260018681016020908152604092839020835160c081018552865481529286015491830191909152918101929092526003830154606083015260048301546080830152600583015460a08301525b81516003820154141561044d57805493506102f2565b600281015460001415610464575b600093506102f2565b6040805160c08101825282548152600183810154602083810191909152600285015483850181905260038601546060850152600486015460808501526005959095015460a0840152600094855290890190529120909150610437565b600383015460001461059757600383810154600090815260018881016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252918101546060830152600481015460808301526005015460a082015291505b60808201516000146102ed57608091820151600090815260018781016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015460608201526004820154938101939093526005015460a0830152610529565b600283015460001461045b5750506002810154600081815260018681016020908152604092839020835160c081018552865481529286015491830191909152918101929092526003830154606083015260048301546080830152600583015460a08301525b81516004820154141561061257805493506102f2565b6002810154600014156106245761045b565b6040805160c08101825282548152600183810154602083810191909152600285015483850181905260038601546060850152600486015460808501526005959095015460a08401526000948552908901905291209091506105fc565b61068a878761015b565b86546000925082141561069b578587555b508554600090815260018701602052604090205b8054600014156107255785815560028101829055600181018590556101b987875b60008181526001830160205260408120905b8154610d8e9085905b60008181526001830160205260408082206004810154835281832060059081015460038301548552929093209092015403905b5092915050565b60018101548154925085126107625760048101546000141561074957600481018690555b60040154600090815260018701602052604090206106af565b60038101546000141561077757600381018690555b60030154600090815260018701602052604090206106af565b600381015460001415806107a957506004810154600014155b156107cf576003810154600014610826578054600188019060009061083b908a90610246565b6002810154600014610a285760028101546000908152600188016020526040902060038101548254919550141561080857600060038501555b60048401548154141561081d57600060048501555b83549150610a2d565b80546001880190600090610852908a906101eb565b815260208101919091526040016000209450610865565b8152602081019190915260400160002094505b600285015460009081526001880160205260409020600381015486549195509092508214156108b9576004850154600385018190556000146108b95760048501546000908152604090208454600282015592505b60048401548554141561091357600385015460048501819055600014610913578660010160005060008660030160005054815260200190815260200160002060005092508250836000016000505483600201600050819055505b60028082015490860181905560001461098457866001016000506000826002016000505481526020019081526020016000206000509350835080600001600050548460030160005054141561096a57845460038501555b60048401548154141561097f57845460048501555b610989565b845487555b6003818101549086018190556000146109d6578660010160005060008260030160005054815260200190815260200160002060005092508250846000016000505483600201600050819055505b600481810154908601819055600014610a23578660010160005060008260040160005054815260200190815260200160002060005092508250846000016000505483600201600050819055505b610a2d565b600087555b6000808255600182018190556002820181905560038201819055600482018190556005820181905582146101b9576101b987836106d0565b50600081815260018601602052604090205b6001810154610a95908686610ad4565b805492505b50509392505050565b15610b915760fa60020a600f02851480610ab6575060f060020a613c3d0285145b15610af157600481015460001415610b3a5780549250610a8c565b86865b600060f960020a601f02831415610ce357508083135b9392505050565b60f960020a601f02851480610b0d575060f060020a613e3d0285145b80610b1f575060f060020a613d3d0285145b15610b9157600381015460001415610bc85780549250610a8c565b610b73610ad1878360040160005054600081815260018301602052604081205b600381015460001415610d61576001810154915061071e565b15610a87576004015460009081526001860160205260409020610a77565b60fa60020a600f02851480610bad575060f060020a613c3d0285145b15610c1f57600381015460001415610c565760009250610a8c565b610c01610ad1878360030160005054600081815260018301602052604081205b600481015460001415610d48576001810154915061071e565b15610a87576003015460009081526001860160205260409020610a77565b60f960020a601f02851480610c3b575060f060020a613e3d0285145b15610c6f57600481015460001415610ca25760009250610a8c565b6003015460009081526001860160205260409020610a77565b60f060020a613d3d02851415610cde57600181015484901215610cbb57600481015460001415610ca25760009250610a8c565b6004015460009081526001860160205260409020610a77565b600181015484901315610cde57600381015460001415610c565760009250610a8c565b610a77565b60fa60020a600f02831415610cfb5750808312610aea565b60f060020a613e3d02831415610d15575080831215610aea565b60f060020a613c3d02831415610d2f575080831315610aea565b60f060020a613d3d028314156100a05750828114610aea565b6004015460009081526001840160205260409020610be8565b6003015460009081526001840160205260409020610b5a565b600282015460001415610fbd575b50505050565b90508060021415610e2657610daa8483600301600050546106eb565b6000191415610dc457610dc4848360030160005054610dfe565b8154610e269085905b60008181526001830160205260408120600381015490919081908190811415610ffb57610007565b8154610e5a9085905b60008181526001830160205260408120600481015490919081908190811415610e7f57610007565b806001191415610e5a57610e418483600401600050546106eb565b60011415610df557610df5848360040160005054610dcd565b8060001913158015610e6d575060018113155b15610d7a578154610d7a908590610f7a565b6004840180546000908152600188016020526040812060028088015490820181905592829055945014610f0f57856001016000506000856002016000505481526020019081526020016000206000509150836000016000505482600301600050541415610efa57826000016000505482600301600050819055505b835460048301541415610f0f57825460048301555b6003830154600014610f40575060038201546000908152600186016020526040902080546004850155835460028201555b82546002808601919091558454600385015583015460001415610f7157826000016000505486600001600050819055505b8354610fe69087905b6000818152600183016020526040808220600381015483528183206005908101546004830154855292842001549092610fd99291908183106110fa5750816100c3565b60029091015460009081526001840160205260409020906106e2565b6001016005820155505050565b8254610ff3908790610f7a565b505050505050565b600384018054600090815260018801602052604081206002808801549082018190559282905594501461108b5785600101600050600085600201600050548152602001908152602001600020600050915083600001600050548260030160005054141561107657826000016000505482600301600050819055505b83546004830154141561108b57825460048301555b60048301546000146110bd57506004820154600081815260018701602052604090206003850191909155835460028201555b82546002808601919091558454600485015583015460001415610f7157826000016000505486600001600050819055508354610fe6908790610f7a565b50806100c356" + }, + "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { + "balance": "0xd7a58f5b73b4b6c4", + "code": "0x606060405236156100985760e060020a60003504633896002781146100e15780633defb962146100ea5780633f4be8891461010c5780634136aa351461011f5780634a420138146101a057806369c1a7121461028c5780638129fc1c146102955780638da5cb5b146102a6578063ae45850b146102b8578063af3309d8146102cc578063ea8a1af0146102d5578063ead50da3146102f4575b610308671bc16d674ec8000030600160a060020a03163110156100df57600554604051600160a060020a03918216916000913091909116319082818181858883f150505050505b565b61030a60005481565b610308671bc16d674ec8000030600160a060020a031631101561040f576100df565b61031c600454600160a060020a03165b90565b61030a5b600080548190118015610199575060408051600480547f0a16697a0000000000000000000000000000000000000000000000000000000083529251600160a060020a039390931692630a16697a928083019260209291829003018187876161da5a03f1156100025750506040515160ff01431090505b905061011c565b6103085b600354600554604080517f8c0e156d0000000000000000000000000000000000000000000000000000000081527f3defb96200000000000000000000000000000000000000000000000000000000600482015260a060020a90920461ffff1643016024830152621e8480604483015251600092600160a060020a031691638c0e156d916729a2241af62c000091606481810192602092909190829003018185886185025a03f1156100025750506040515192600160a060020a0384161491506102899050576004805473ffffffffffffffffffffffffffffffffffffffff1916821790555b50565b61030a60015481565b61030860008054146103f2576100df565b61031c600554600160a060020a031681565b61031c600354600160a060020a031661011c565b61030a60025481565b610308600554600160a060020a03908116339091161461035157610002565b61033960055460a060020a900461ffff1681565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b6004546000600160a060020a03919091163111156103c75760408051600480547fea8a1af00000000000000000000000000000000000000000000000000000000083529251600160a060020a03939093169263ea8a1af0928083019260009291829003018183876161da5a03f115610002575050505b600554604051600160a060020a03918216916000913091909116319082818181858883f15050505050565b426000556100df6101a4565b600280546001908101909155429055565b600454600160a060020a03908116339091161461042b576100df565b610433610123565b151561043e576100df565b6103fe6101a456", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000056be5b99", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000056d0009b", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000008b", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000006c8f2a135f6ed072de4503bd7c4999a1a17f824b", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000001e0d3cda913deb6f67967b99d67acdfa1712c293601" + } + }, + "0x89efe605e9ecbe22849cd85d5449cc946c26f8f3": { + "balance": "0x0", + "code": "0x650200d2f18c73506060604052361561007f5760e060020a600035046312c82bcc81146100845780635548c837146100a55780635c54305e146101015780636b103966146101555780637fcf532c14610189578063b1df3d80146101d5578063b5bc6dbb146101ee578063c6ab451414610225578063e62af6c114610293575b610007565b6102c56004356024356000620186a05a10156103855761030083835a610232565b6102d760043560243560443581600160a060020a031683600160a060020a03167f47a08955ce2b7f21ea62ff0024e1ea0ad87430953554a87e6bc65d777f18e639836040518082815260200191505060405180910390a3505050565b6102d760043560243560443560408051838152602081018390528151600160a060020a038616927f9b24879829bed3003de08d5c5d7e18dcbb8dc76faebd95cafc5d4dec8c61a3a5928290030190a2505050565b6102d76004356024356044355b600160a060020a03821660009081526020849052604090205480820110156102d957610007565b6102d7600435602435604080518281529051600160a060020a038416917fd0c5cf41ee8ebf084ad0bce53de7cbc6e4693d9b53a4019ca36a2f91cdc20b3a919081900360200190a25050565b6102c560043560243560443560006102fc848484610162565b6102c5600435602435604435600160a060020a03821660009081526020849052604081205482901061032b576103338484846102a0565b6102c56004356024356044355b60006000831180156102605750604051600160a060020a038516908290859082818181858883f19350505050155b156102fc57604051600160a060020a03851690839085906000818181858888f1935050505015156102fc57506000610300565b6102d76004356024356044355b600160a060020a03821660009081526020849052604090205481111561030757610007565b60408051918252519081900360200190f35b005b600160a060020a0382166000908152602084905260409020805482019055505050565b5060015b9392505050565b600160a060020a038216600090815260208490526040902080548290039055505050565b506000610300565b604051600160a060020a03841690600090849082818181858883f1935050505015156102fc57604051600160a060020a038416908390600081818185876185025a03f19250505015156102fc57610007565b6103008383620186a061023256" + }, + "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { + "balance": "0xffe9b09a5c474dca", + "nonce": "975", + "code": "0x" + }, + "0xd3cda913deb6f67967b99d67acdfa1712c293601": { + "balance": "0x4f5807198e238f13e", + "nonce": "283", + "code": "0x" + }, + "0xe54d323f9ef17c1f0dede47ecc86a9718fe5ea34": { + "balance": "0x0", + "code": "0x650200d2f18c7350606060405236156100ab5760e060020a600035046326a7985a81146100b057806350d4e411146100be57806354fd4d501461023d578063586a69fa1461025d5780638e46afa91461026857806396cff3df14610272578063971c803f1461029657806398c9cdf4146102a157806398e00e54146102ae578063b152f19e146102b8578063c0f68859146102c4578063e3042c0f146102cf578063ea27a88114610461575b610007565b6102845b60006104cb6102a5565b604080516020601f60843560048181013592830184900484028501840190955281845261047f948035946024803595604435956064359560a494930191819084018382808284375094965050933593505060c43591505060e435610104356101243561014435610164356101843560006101806040519081016040528060008152602001600081526020016000815260200160206040519081016040528060008152602001508152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200150610180604051908101604052808f81526020018e81526020018d81526020018c81526020018981526020018b81526020018a81526020018881526020018781526020018681526020018581526020018481526020015090506104d48f825b600060006000600a43018460e0015110156105de577f544f4f5f534f4f4e0000000000000000000000000000000000000000000000009150610524565b604080516000808252600760208301528183015290519081900360600190f35b61049c5b6103e85b90565b6104b460ff610265565b62030d403a0260026024356004350102015b60408051918252519081900360200190f35b61049c5b600a610265565b6102845b62030d40610265565b6102846010610265565b61028443600a01610265565b6102845b6020610265565b60408051808201825261047f916004803592909160649190602490600290839083908082843780516020601f608435808c01359182018390048302840183019094528083529499983598975060a49650909450910191908190840183828082843750506040805160c0818101909252959796359660c435969095506101a49450925060e491506006908390839080828437509095505050505050604080516101808181018352600080835260208381018290528385018290528451908101855281815260608401526080830181905260a0830181905260c0830181905260e0830181905261010083018190526101208301819052610140830181905261016083018190528351918201909352808984505181526020018960015060209081015182528101899052604081018890526060018484505181526020810187905260408101869052606001846001506020908101518252018460025060400151815260200184600350606001518152602001846004506080015181526020018460055060a00151905290506104e78982610200565b6102846004356024356044356064355b3a0291909201600202010190565b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b6040805160ff929092168252519081900360200190f35b45039050610265565b9f9e505050505050505050505050505050565b9998505050505050505050565b8461016001511015610524577f494e53554646494349454e545f46554e4453000000000000000000000000000091505b600082146106ed576040805185518482529151600160a060020a0392909216917f513485fc54ef019ef1bc1ea683ef7d5d522f2865224ae10871ff992749c0ba4f9181900360200190a27389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc85600001518661016001516040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f215610007575050505b505092915050565b8360c0015161ffff166105ef61029a565b61ffff1611806106115750610602610261565b61ffff168460c0015161ffff16115b1561063e577f535441434b5f434845434b5f4f55545f4f465f52414e474500000000000000009150610524565b6106466102c8565b8460a0015160ff16101561067c577f47524143455f544f4f5f53484f525400000000000000000000000000000000009150610524565b6106846102a5565b84610100015110806106a157506106996100b4565b846101000151115b156106ce577f52455155495245445f4741535f4f55545f4f465f52414e4745000000000000009150610524565b6104f48461012001518561014001518660800151876101000151610471565b83610160015184600001518560e001518660a001518760200151886040015189606001518a608001518b61010001518c60c001518d61012001518e6101400151604051611078806108fa833901808c600160a060020a031681526020018b81526020018a60ff16815260200189600160a060020a03168152602001888152602001806020018781526020018681526020018561ffff1681526020018481526020018381526020018281038252888181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156107ec5780820380516001836020036101000a031916815260200191505b509c505050505050505050505050506040518091039082f090509050737c1eb207c07e7ab13cf245585bd03d0fa478d03463bacd69588683600160a060020a031660010284600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505050604051805190602001506040518460e060020a02815260040180848152602001838152602001828152602001935050505060006040518083038160008760325a03f21561000757505060408051600160a060020a038416815290517f2b05d346f0b0b9fd470024751c52d3b5dac5c37796f077c1a66241f2eada44b792509081900360200190a18092506105d656606060405260405161107838038061107883398101604052805160805160a05160c05160e05161010051610120516101405161016051610180516101a051999a98999798969795969490940194929391929091908a84848a8a8a8a88886101008051600c8054600160a060020a031990811633179091556000805482168d1781556001868155600286815560078e90556008805461ffff19168e1790553a600655600380547c01000000000000000000000000000000000000000000000000000000008d04740100000000000000000000000000000000000000000260a060020a63ffffffff0219919096168e17169490941790935588516004805493819052956020601f9385161590910260001901909316939093048101919091047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b908101939091608091909101908390106101ee57805160ff19168380011785555b5061017a9291505b8082111561021e5760008155600101610166565b5050826003600050600201600050819055505050505050505050508a600060006101000a815481600160a060020a030219169083021790555089600d6000508190555088600e60006101000a81548160ff021916908302179055505050505050505050505050610e56806102226000396000f35b8280016001018555821561015e579182015b8281111561015e578251826000505591602001919060010190610200565b509056606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256" + } + }, + "config": { + "chainId": 1, + "homesteadBlock": 1150000, + "daoForkBlock": 1920000, + "eip150Block": 2463000, + "eip155Block": 2675000, + "eip158Block": 2675000, + "byzantiumBlock": 4370000, + "constantinopleBlock": 7280000, + "petersburgBlock": 7280000, + "istanbulBlock": 9069000, + "muirGlacierBlock": 9200000, + "berlinBlock": 12244000, + "londonBlock": 12965000, + "arrowGlacierBlock": 13773000, + "grayGlacierBlock": 15050000, + "ethash": {} + } + }, + "context": { + "number": "1062503", + "difficulty": "13700504019867", + "timestamp": "1456480446", + "gasLimit": "3141592", + "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" + }, + "input": "0xf86b8203cf850ba43b740083200b2094741467b251fca923d6229c4b439078b55dca233b8084614619541ca078293714f69a810356f1ee29dc686ec2ca3a0e5448e1ef6322c77369ebdd26c2a01c3836fa363548959554ee5360361be9db4aea9eb7c31f61550f0e9a10138adf", + "tracerConfig": { + "diffMode": true, + "disableCode": true, + "disableStorage": true + }, + "result": { + "pre": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x98e1c608601c2496b2", + "nonce": 218916 + }, + "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { + "balance": "0x0", + "nonce": 237 + }, + "0x741467b251fca923d6229c4b439078b55dca233b": { + "balance": "0x29c613529e8218f8" + }, + "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { + "balance": "0xd7a58f5b73b4b6c4" + }, + "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { + "balance": "0xffe9b09a5c474dca", + "nonce": 975 + }, + "0xd3cda913deb6f67967b99d67acdfa1712c293601": { + "balance": "0x4f5807198e238f13e", + "nonce": 283 + } + }, + "post": { + "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { + "balance": "0x98e2b02f14529b1eb2" + }, + "0x651913977e8140c323997fce5e03c19e0015eebf": { + "balance": "0x29a2241af62c0000" + }, + "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { + "nonce": 238 + }, + "0x741467b251fca923d6229c4b439078b55dca233b": { + "balance": "0x0" + }, + "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { + "balance": "0xd6c5f42b8502a0e3" + }, + "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { + "balance": "0x10002e64ebd492a46", + "nonce": 976 + }, + "0xd3cda913deb6f67967b99d67acdfa1712c293601": { + "balance": "0x4f5809f97e1c8bb9b" + } + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json new file mode 100644 index 0000000000..5f939ba2df --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json @@ -0,0 +1,101 @@ +{ + "context": { + "difficulty": "3502894804", + "gasLimit": "4722976", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2289806", + "timestamp": "1513601314" + }, + "genesis": { + "alloc": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "code": "0x", + "nonce": "22", + "storage": {} + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "code": "0x", + "nonce": "29072", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "eip150Block": 0, + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3509749784", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4727564", + "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", + "nonce": "0x4eb12e19c16d43da", + "number": "2289805", + "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", + "timestamp": "1513601261", + "totalDifficulty": "7143276353481064" + }, + "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", + "tracerConfig": { + "diffMode": true + }, + "result": { + "pre": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "nonce": 22 + }, + "0x1585936b53834b021f68cc13eeefdec2efc8e724": { + "balance": "0x0" + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d87094125a369d9bd5", + "nonce": 1, + "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d77678137ac1b775", + "nonce": 29072 + } + }, + "post": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x6f05b59d3b20000" + }, + "0x1585936b53834b021f68cc13eeefdec2efc8e724": { + "balance": "0x420eed1bd6c00" + }, + "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { + "balance": "0x4d869a3b70062eb9bd5", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b95e" + } + }, + "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { + "balance": "0x1780d7725724a9044b75", + "nonce": 29073 + } + } + } +} diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index b7cc60b096..e56d011139 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -55,6 +55,7 @@ var parityErrorMapping = map[string]string{ } var parityErrorMappingStartingWith = map[string]string{ + "out of gas:": "Out of gas", // convert OOG wrapped errors, eg `out of gas: not enough gas for reentrancy sentry` "invalid opcode:": "Bad instruction", "stack underflow": "Stack underflow", } @@ -296,10 +297,11 @@ func newFlatCreate(input *callFrame) *flatCallFrame { return &flatCallFrame{ Type: strings.ToLower(vm.CREATE.String()), Action: flatCallAction{ - From: &input.From, - Gas: &input.Gas, - Value: input.Value, - Init: &actionInit, + CreationMethod: strings.ToLower(input.Type.String()), + From: &input.From, + Gas: &input.Gas, + Value: input.Value, + Init: &actionInit, }, Result: &flatCallResult{ GasUsed: &input.GasUsed, @@ -370,6 +372,7 @@ func convertErrorToParity(call *flatCallFrame) { for gethError, parityError := range parityErrorMappingStartingWith { if strings.HasPrefix(call.Error, gethError) { call.Error = parityError + break } } } diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index 978ba0670c..9706eb43f6 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -72,7 +72,9 @@ type prestateTracer struct { } type prestateTracerConfig struct { - DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications + DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications + DisableCode bool `json:"disableCode"` // If true, this tracer will not return the contract code + DisableStorage bool `json:"disableStorage"` // If true, this tracer will not return the contract storage } func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) { @@ -210,7 +212,6 @@ func (t *prestateTracer) processDiffState() { postAccount := &account{Storage: make(map[common.Hash]common.Hash)} newBalance := t.env.StateDB.GetBalance(addr).ToBig() newNonce := t.env.StateDB.GetNonce(addr) - newCode := t.env.StateDB.GetCode(addr) if newBalance.Cmp(t.pre[addr].Balance) != 0 { modified = true @@ -220,25 +221,30 @@ func (t *prestateTracer) processDiffState() { modified = true postAccount.Nonce = newNonce } - if !bytes.Equal(newCode, t.pre[addr].Code) { - modified = true - postAccount.Code = newCode + if !t.config.DisableCode { + newCode := t.env.StateDB.GetCode(addr) + if !bytes.Equal(newCode, t.pre[addr].Code) { + modified = true + postAccount.Code = newCode + } } - for key, val := range state.Storage { - // don't include the empty slot - if val == (common.Hash{}) { - delete(t.pre[addr].Storage, key) - } + if !t.config.DisableStorage { + for key, val := range state.Storage { + // don't include the empty slot + if val == (common.Hash{}) { + delete(t.pre[addr].Storage, key) + } - newVal := t.env.StateDB.GetState(addr, key) - if val == newVal { - // Omit unchanged slots - delete(t.pre[addr].Storage, key) - } else { - modified = true - if newVal != (common.Hash{}) { - postAccount.Storage[key] = newVal + newVal := t.env.StateDB.GetState(addr, key) + if val == newVal { + // Omit unchanged slots + delete(t.pre[addr].Storage, key) + } else { + modified = true + if newVal != (common.Hash{}) { + postAccount.Storage[key] = newVal + } } } } @@ -263,11 +269,17 @@ func (t *prestateTracer) lookupAccount(addr common.Address) { Balance: t.env.StateDB.GetBalance(addr).ToBig(), Nonce: t.env.StateDB.GetNonce(addr), Code: t.env.StateDB.GetCode(addr), - Storage: make(map[common.Hash]common.Hash), } if !acc.exists() { acc.empty = true } + // The code must be fetched first for the emptiness check. + if t.config.DisableCode { + acc.Code = nil + } + if !t.config.DisableStorage { + acc.Storage = make(map[common.Hash]common.Hash) + } t.pre[addr] = acc } @@ -275,6 +287,9 @@ func (t *prestateTracer) lookupAccount(addr common.Address) { // it to the prestate of the given contract. It assumes `lookupAccount` // has been performed on the contract before. func (t *prestateTracer) lookupStorage(addr common.Address, key common.Hash) { + if t.config.DisableStorage { + return + } if _, ok := t.pre[addr].Storage[key]; ok { return } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 3cce7bffa1..31e14b9112 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -99,11 +99,13 @@ func BenchmarkTransactionTrace(b *testing.B) { for i := 0; i < b.N; i++ { snap := state.StateDB.Snapshot() + tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - _, err = st.TransitionDb() + res, err := st.TransitionDb() if err != nil { b.Fatal(err) } + tracer.OnTxEnd(&types.Receipt{GasUsed: res.UsedGas}, nil) state.StateDB.RevertToSnapshot(snap) if have, want := len(tracer.StructLogs()), 244752; have != want { b.Fatalf("trace wrong, want %d steps, have %d", want, have) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 0972644d80..f10626c01f 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -630,6 +630,23 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) } +// RevertErrorData returns the 'revert reason' data of a contract call. +// +// This can be used with CallContract and EstimateGas, and only when the server is Geth. +func RevertErrorData(err error) ([]byte, bool) { + var ec rpc.Error + var ed rpc.DataError + if errors.As(err, &ec) && errors.As(err, &ed) && ec.ErrorCode() == 3 { + if eds, ok := ed.ErrorData().(string); ok { + revertData, err := hexutil.Decode(eds) + if err == nil { + return revertData, true + } + } + } + return nil, false +} + func toBlockNumArg(number *big.Int) string { if number == nil { return "latest" diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 1b7e26fb74..4ad8a552d2 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -14,18 +14,20 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package ethclient +package ethclient_test import ( "bytes" "context" "errors" + "fmt" "math/big" "reflect" "testing" "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -33,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" @@ -40,154 +43,33 @@ import ( // Verify that Client implements the ethereum interfaces. var ( - _ = ethereum.ChainReader(&Client{}) - _ = ethereum.TransactionReader(&Client{}) - _ = ethereum.ChainStateReader(&Client{}) - _ = ethereum.ChainSyncReader(&Client{}) - _ = ethereum.ContractCaller(&Client{}) - _ = ethereum.GasEstimator(&Client{}) - _ = ethereum.GasPricer(&Client{}) - _ = ethereum.LogFilterer(&Client{}) - _ = ethereum.PendingStateReader(&Client{}) - // _ = ethereum.PendingStateEventer(&Client{}) - _ = ethereum.PendingContractCaller(&Client{}) + _ = ethereum.ChainReader(ðclient.Client{}) + _ = ethereum.TransactionReader(ðclient.Client{}) + _ = ethereum.ChainStateReader(ðclient.Client{}) + _ = ethereum.ChainSyncReader(ðclient.Client{}) + _ = ethereum.ContractCaller(ðclient.Client{}) + _ = ethereum.GasEstimator(ðclient.Client{}) + _ = ethereum.GasPricer(ðclient.Client{}) + _ = ethereum.LogFilterer(ðclient.Client{}) + _ = ethereum.PendingStateReader(ðclient.Client{}) + // _ = ethereum.PendingStateEventer(ðclient.Client{}) + _ = ethereum.PendingContractCaller(ðclient.Client{}) ) -func TestToFilterArg(t *testing.T) { - blockHashErr := errors.New("cannot specify both BlockHash and FromBlock/ToBlock") - addresses := []common.Address{ - common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"), - } - blockHash := common.HexToHash( - "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", - ) - - for _, testCase := range []struct { - name string - input ethereum.FilterQuery - output interface{} - err error - }{ - { - "without BlockHash", - ethereum.FilterQuery{ - Addresses: addresses, - FromBlock: big.NewInt(1), - ToBlock: big.NewInt(2), - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "0x1", - "toBlock": "0x2", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with nil fromBlock and nil toBlock", - ethereum.FilterQuery{ - Addresses: addresses, - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "0x0", - "toBlock": "latest", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with negative fromBlock and negative toBlock", - ethereum.FilterQuery{ - Addresses: addresses, - FromBlock: big.NewInt(-1), - ToBlock: big.NewInt(-1), - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "pending", - "toBlock": "pending", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with blockhash", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "blockHash": blockHash, - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with blockhash and from block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - FromBlock: big.NewInt(1), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - { - "with blockhash and to block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - ToBlock: big.NewInt(1), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - { - "with blockhash and both from / to block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - FromBlock: big.NewInt(1), - ToBlock: big.NewInt(2), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - output, err := toFilterArg(testCase.input) - if (testCase.err == nil) != (err == nil) { - t.Fatalf("expected error %v but got %v", testCase.err, err) - } - if testCase.err != nil { - if testCase.err.Error() != err.Error() { - t.Fatalf("expected error %v but got %v", testCase.err, err) - } - } else if !reflect.DeepEqual(testCase.output, output) { - t.Fatalf("expected filter arg %v but got %v", testCase.output, output) - } - }) - } -} - var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - testBalance = big.NewInt(2e15) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + testAddr = crypto.PubkeyToAddress(testKey.PublicKey) + testBalance = big.NewInt(2e15) + revertContractAddr = common.HexToAddress("290f1b36649a61e369c6276f6d29463335b4400c") + revertCode = common.FromHex("7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f75736572206572726f7200000000000000000000000000000000000000000000604452604e6000fd") ) var genesis = &core.Genesis{ - Config: params.AllEthashProtocolChanges, - Alloc: types.GenesisAlloc{testAddr: {Balance: testBalance}}, + Config: params.AllEthashProtocolChanges, + Alloc: types.GenesisAlloc{ + testAddr: {Balance: testBalance}, + revertContractAddr: {Code: revertCode}, + }, ExtraData: []byte("test genesis"), Timestamp: 9000, BaseFee: big.NewInt(params.InitialBaseFee), @@ -209,27 +91,30 @@ var testTx2 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), & To: &common.Address{2}, }) -func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { +func newTestBackend(config *node.Config) (*node.Node, []*types.Block, error) { // Generate test chain. blocks := generateTestChain() // Create node - n, err := node.New(&node.Config{}) + if config == nil { + config = new(node.Config) + } + n, err := node.New(config) if err != nil { - t.Fatalf("can't create new node: %v", err) + return nil, nil, fmt.Errorf("can't create new node: %v", err) } // Create Ethereum Service - config := ðconfig.Config{Genesis: genesis, RPCGasCap: 1000000} - ethservice, err := eth.New(n, config) + ecfg := ðconfig.Config{Genesis: genesis, RPCGasCap: 1000000} + ethservice, err := eth.New(n, ecfg) if err != nil { - t.Fatalf("can't create new ethereum service: %v", err) + return nil, nil, fmt.Errorf("can't create new ethereum service: %v", err) } // Import the test chain. if err := n.Start(); err != nil { - t.Fatalf("can't start test node: %v", err) + return nil, nil, fmt.Errorf("can't start test node: %v", err) } if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil { - t.Fatalf("can't import test blocks: %v", err) + return nil, nil, fmt.Errorf("can't import test blocks: %v", err) } // Ensure the tx indexing is fully generated for ; ; time.Sleep(time.Millisecond * 100) { @@ -238,7 +123,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { break } } - return n, blocks + return n, blocks, nil } func generateTestChain() []*types.Block { @@ -256,7 +141,10 @@ func generateTestChain() []*types.Block { } func TestEthClient(t *testing.T) { - backend, chain := newTestBackend(t) + backend, chain, err := newTestBackend(nil) + if err != nil { + t.Fatal(err) + } client := backend.Attach() defer backend.Close() defer client.Close() @@ -324,7 +212,7 @@ func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) { } for name, tt := range tests { t.Run(name, func(t *testing.T) { - ec := NewClient(client) + ec := ethclient.NewClient(client) ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() @@ -373,7 +261,7 @@ func testBalanceAt(t *testing.T, client *rpc.Client) { } for name, tt := range tests { t.Run(name, func(t *testing.T) { - ec := NewClient(client) + ec := ethclient.NewClient(client) ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() @@ -389,7 +277,7 @@ func testBalanceAt(t *testing.T, client *rpc.Client) { } func testTransactionInBlock(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) // Get current block by number. block, err := ec.BlockByNumber(context.Background(), nil) @@ -421,7 +309,7 @@ func testTransactionInBlock(t *testing.T, client *rpc.Client) { } func testChainID(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) id, err := ec.ChainID(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -432,7 +320,7 @@ func testChainID(t *testing.T, client *rpc.Client) { } func testGetBlock(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) // Get current block number blockNumber, err := ec.BlockNumber(context.Background()) @@ -477,7 +365,7 @@ func testGetBlock(t *testing.T, client *rpc.Client) { } func testStatusFunctions(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) // Sync progress progress, err := ec.SyncProgress(context.Background()) @@ -540,7 +428,7 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) { } func testCallContractAtHash(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) // EstimateGas msg := ethereum.CallMsg{ @@ -567,7 +455,7 @@ func testCallContractAtHash(t *testing.T, client *rpc.Client) { } func testCallContract(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) // EstimateGas msg := ethereum.CallMsg{ @@ -594,7 +482,7 @@ func testCallContract(t *testing.T, client *rpc.Client) { } func testAtFunctions(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1)) if err != nil { @@ -697,7 +585,7 @@ func testAtFunctions(t *testing.T, client *rpc.Client) { } func testTransactionSender(t *testing.T, client *rpc.Client) { - ec := NewClient(client) + ec := ethclient.NewClient(client) ctx := context.Background() // Retrieve testTx1 via RPC. @@ -737,7 +625,7 @@ func testTransactionSender(t *testing.T, client *rpc.Client) { } } -func sendTransaction(ec *Client) error { +func sendTransaction(ec *ethclient.Client) error { chainID, err := ec.ChainID(context.Background()) if err != nil { return err @@ -760,3 +648,40 @@ func sendTransaction(ec *Client) error { } return ec.SendTransaction(context.Background(), tx) } + +// Here we show how to get the error message of reverted contract call. +func ExampleRevertErrorData() { + // First create an ethclient.Client instance. + ctx := context.Background() + ec, _ := ethclient.DialContext(ctx, exampleNode.HTTPEndpoint()) + + // Call the contract. + // Note we expect the call to return an error. + contract := common.HexToAddress("290f1b36649a61e369c6276f6d29463335b4400c") + call := ethereum.CallMsg{To: &contract, Gas: 30000} + result, err := ec.CallContract(ctx, call, nil) + if len(result) > 0 { + panic("got result") + } + if err == nil { + panic("call did not return error") + } + + // Extract the low-level revert data from the error. + revertData, ok := ethclient.RevertErrorData(err) + if !ok { + panic("unpacking revert failed") + } + fmt.Printf("revert: %x\n", revertData) + + // Parse the revert data to obtain the error message. + message, err := abi.UnpackRevert(revertData) + if err != nil { + panic("parsing ABI error failed: " + err.Error()) + } + fmt.Println("message:", message) + + // Output: + // revert: 08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a75736572206572726f72 + // message: user error +} diff --git a/console/bridge_test.go b/ethclient/example_test.go similarity index 52% rename from console/bridge_test.go rename to ethclient/example_test.go index e57e294fc5..5d0038f0c7 100644 --- a/console/bridge_test.go +++ b/ethclient/example_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 The go-ethereum Authors +// 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 @@ -14,35 +14,22 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package console +package ethclient_test import ( - "testing" - - "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/internal/jsre" + "github.com/ethereum/go-ethereum/node" ) -// TestUndefinedAsParam ensures that personal functions can receive -// `undefined` as a parameter. -func TestUndefinedAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Undefined()} +var exampleNode *node.Node - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) -} - -// TestNullAsParam ensures that personal functions can receive -// `null` as a parameter. -func TestNullAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Null()} - - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) +// launch example server +func init() { + config := &node.Config{ + HTTPHost: "127.0.0.1", + } + n, _, err := newTestBackend(config) + if err != nil { + panic("can't launch node: " + err.Error()) + } + exampleNode = n } diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 36ea290a85..65d006d1e6 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -21,6 +21,7 @@ import ( "context" "encoding/json" "math/big" + "strings" "testing" "github.com/ethereum/go-ethereum" @@ -164,55 +165,85 @@ func TestGethClient(t *testing.T) { func testAccessList(t *testing.T, client *rpc.Client) { ec := New(client) - // Test transfer - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 21000, - GasPrice: big.NewInt(875000000), - Value: big.NewInt(1), - } - al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if vmErr != "" { - t.Fatalf("unexpected vm error: %v", vmErr) - } - if gas != 21000 { - t.Fatalf("unexpected gas used: %v", gas) - } - if len(*al) != 0 { - t.Fatalf("unexpected length of accesslist: %v", len(*al)) - } - // Test reverting transaction - msg = ethereum.CallMsg{ - From: testAddr, - To: nil, - Gas: 100000, - GasPrice: big.NewInt(1000000000), - Value: big.NewInt(1), - Data: common.FromHex("0x608060806080608155fd"), - } - al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if vmErr == "" { - t.Fatalf("wanted vmErr, got none") - } - if gas == 21000 { - t.Fatalf("unexpected gas used: %v", gas) - } - if len(*al) != 1 || al.StorageKeys() != 1 { - t.Fatalf("unexpected length of accesslist: %v", len(*al)) - } - // address changes between calls, so we can't test for it. - if (*al)[0].Address == common.HexToAddress("0x0") { - t.Fatalf("unexpected address: %v", (*al)[0].Address) - } - if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") { - t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0]) + + for i, tc := range []struct { + msg ethereum.CallMsg + wantGas uint64 + wantErr string + wantVMErr string + wantAL string + }{ + { // Test transfer + msg: ethereum.CallMsg{ + From: testAddr, + To: &common.Address{}, + Gas: 21000, + GasPrice: big.NewInt(875000000), + Value: big.NewInt(1), + }, + wantGas: 21000, + wantAL: `[]`, + }, + { // Test reverting transaction + msg: ethereum.CallMsg{ + From: testAddr, + To: nil, + Gas: 100000, + GasPrice: big.NewInt(1000000000), + Value: big.NewInt(1), + Data: common.FromHex("0x608060806080608155fd"), + }, + wantGas: 77496, + wantVMErr: "execution reverted", + wantAL: `[ + { + "address": "0x3a220f351252089d385b29beca14e27f204c296a", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000081" + ] + } +]`, + }, + { // error when gasPrice is less than baseFee + msg: ethereum.CallMsg{ + From: testAddr, + To: &common.Address{}, + Gas: 21000, + GasPrice: big.NewInt(1), // less than baseFee + Value: big.NewInt(1), + }, + wantErr: "max fee per gas less than block base fee", + }, + { // when gasPrice is not specified + msg: ethereum.CallMsg{ + From: testAddr, + To: &common.Address{}, + Gas: 21000, + Value: big.NewInt(1), + }, + wantGas: 21000, + wantAL: `[]`, + }, + } { + al, gas, vmErr, err := ec.CreateAccessList(context.Background(), tc.msg) + if tc.wantErr != "" { + if !strings.Contains(err.Error(), tc.wantErr) { + t.Fatalf("test %d: wrong error: %v", i, err) + } + continue + } else if err != nil { + t.Fatalf("test %d: wrong error: %v", i, err) + } + if have, want := vmErr, tc.wantVMErr; have != want { + t.Fatalf("test %d: vmErr wrong, have %v want %v", i, have, want) + } + if have, want := gas, tc.wantGas; have != want { + t.Fatalf("test %d: gas wrong, have %v want %v", i, have, want) + } + haveList, _ := json.MarshalIndent(al, "", " ") + if have, want := string(haveList), tc.wantAL; have != want { + t.Fatalf("test %d: access list wrong, have:\n%v\nwant:\n%v", i, have, want) + } } } diff --git a/ethclient/types_test.go b/ethclient/types_test.go new file mode 100644 index 0000000000..02f9f21758 --- /dev/null +++ b/ethclient/types_test.go @@ -0,0 +1,153 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package ethclient + +import ( + "errors" + "math/big" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" +) + +func TestToFilterArg(t *testing.T) { + blockHashErr := errors.New("cannot specify both BlockHash and FromBlock/ToBlock") + addresses := []common.Address{ + common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"), + } + blockHash := common.HexToHash( + "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", + ) + + for _, testCase := range []struct { + name string + input ethereum.FilterQuery + output interface{} + err error + }{ + { + "without BlockHash", + ethereum.FilterQuery{ + Addresses: addresses, + FromBlock: big.NewInt(1), + ToBlock: big.NewInt(2), + Topics: [][]common.Hash{}, + }, + map[string]interface{}{ + "address": addresses, + "fromBlock": "0x1", + "toBlock": "0x2", + "topics": [][]common.Hash{}, + }, + nil, + }, + { + "with nil fromBlock and nil toBlock", + ethereum.FilterQuery{ + Addresses: addresses, + Topics: [][]common.Hash{}, + }, + map[string]interface{}{ + "address": addresses, + "fromBlock": "0x0", + "toBlock": "latest", + "topics": [][]common.Hash{}, + }, + nil, + }, + { + "with negative fromBlock and negative toBlock", + ethereum.FilterQuery{ + Addresses: addresses, + FromBlock: big.NewInt(-1), + ToBlock: big.NewInt(-1), + Topics: [][]common.Hash{}, + }, + map[string]interface{}{ + "address": addresses, + "fromBlock": "pending", + "toBlock": "pending", + "topics": [][]common.Hash{}, + }, + nil, + }, + { + "with blockhash", + ethereum.FilterQuery{ + Addresses: addresses, + BlockHash: &blockHash, + Topics: [][]common.Hash{}, + }, + map[string]interface{}{ + "address": addresses, + "blockHash": blockHash, + "topics": [][]common.Hash{}, + }, + nil, + }, + { + "with blockhash and from block", + ethereum.FilterQuery{ + Addresses: addresses, + BlockHash: &blockHash, + FromBlock: big.NewInt(1), + Topics: [][]common.Hash{}, + }, + nil, + blockHashErr, + }, + { + "with blockhash and to block", + ethereum.FilterQuery{ + Addresses: addresses, + BlockHash: &blockHash, + ToBlock: big.NewInt(1), + Topics: [][]common.Hash{}, + }, + nil, + blockHashErr, + }, + { + "with blockhash and both from / to block", + ethereum.FilterQuery{ + Addresses: addresses, + BlockHash: &blockHash, + FromBlock: big.NewInt(1), + ToBlock: big.NewInt(2), + Topics: [][]common.Hash{}, + }, + nil, + blockHashErr, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + output, err := toFilterArg(testCase.input) + if (testCase.err == nil) != (err == nil) { + t.Fatalf("expected error %v but got %v", testCase.err, err) + } + if testCase.err != nil { + if testCase.err.Error() != err.Error() { + t.Fatalf("expected error %v but got %v", testCase.err, err) + } + } else if !reflect.DeepEqual(testCase.output, output) { + t.Fatalf("expected filter arg %v but got %v", testCase.output, output) + } + }) + } +} diff --git a/ethdb/database.go b/ethdb/database.go index c6e76fd2fe..323f8f5d6f 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -37,6 +37,13 @@ type KeyValueWriter interface { Delete(key []byte) error } +// KeyValueRangeDeleter wraps the DeleteRange method of a backing data store. +type KeyValueRangeDeleter interface { + // DeleteRange deletes all of the keys (and values) in the range [start,end) + // (inclusive on start, exclusive on end). + DeleteRange(start, end []byte) error +} + // KeyValueStater wraps the Stat method of a backing data store. type KeyValueStater interface { // Stat returns the statistic data of the database. @@ -61,6 +68,7 @@ type KeyValueStore interface { KeyValueReader KeyValueWriter KeyValueStater + KeyValueRangeDeleter Batcher Iteratee Compacter @@ -154,25 +162,12 @@ type Reader interface { AncientReader } -// Writer contains the methods required to write data to both key-value as well as -// immutable ancient data. -type Writer interface { - KeyValueWriter - AncientWriter -} - -// Stater contains the methods required to retrieve states from both key-value as well as -// immutable ancient data. -type Stater interface { - KeyValueStater - AncientStater -} - // AncientStore contains all the methods required to allow handling different // ancient data stores backing immutable data store. type AncientStore interface { AncientReader AncientWriter + AncientStater io.Closer } @@ -187,11 +182,6 @@ type ResettableAncientStore interface { // Database contains all the methods required by the high level database to not // only access the key-value data store but also the ancient chain store. type Database interface { - Reader - Writer - Batcher - Iteratee - Stater - Compacter - io.Closer + KeyValueStore + AncientStore } diff --git a/ethdb/dbtest/testsuite.go b/ethdb/dbtest/testsuite.go index 1af55a0e38..52e6b287cf 100644 --- a/ethdb/dbtest/testsuite.go +++ b/ethdb/dbtest/testsuite.go @@ -21,6 +21,7 @@ import ( "crypto/rand" "slices" "sort" + "strconv" "testing" "github.com/ethereum/go-ethereum/ethdb" @@ -343,6 +344,64 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) { t.Fatalf("expected error on batch.Write after Close") } }) + + t.Run("DeleteRange", func(t *testing.T) { + db := New() + defer db.Close() + + addRange := func(start, stop int) { + for i := start; i <= stop; i++ { + db.Put([]byte(strconv.Itoa(i)), nil) + } + } + + checkRange := func(start, stop int, exp bool) { + for i := start; i <= stop; i++ { + has, _ := db.Has([]byte(strconv.Itoa(i))) + if has && !exp { + t.Fatalf("unexpected key %d", i) + } + if !has && exp { + t.Fatalf("missing expected key %d", i) + } + } + } + + addRange(1, 9) + db.DeleteRange([]byte("9"), []byte("1")) + checkRange(1, 9, true) + db.DeleteRange([]byte("5"), []byte("5")) + checkRange(1, 9, true) + db.DeleteRange([]byte("5"), []byte("50")) + checkRange(1, 4, true) + checkRange(5, 5, false) + checkRange(6, 9, true) + db.DeleteRange([]byte(""), []byte("a")) + checkRange(1, 9, false) + + addRange(1, 999) + db.DeleteRange([]byte("12345"), []byte("54321")) + checkRange(1, 1, true) + checkRange(2, 5, false) + checkRange(6, 12, true) + checkRange(13, 54, false) + checkRange(55, 123, true) + checkRange(124, 543, false) + checkRange(544, 999, true) + + addRange(1, 999) + db.DeleteRange([]byte("3"), []byte("7")) + checkRange(1, 2, true) + checkRange(3, 6, false) + checkRange(7, 29, true) + checkRange(30, 69, false) + checkRange(70, 299, true) + checkRange(300, 699, false) + checkRange(700, 999, true) + + db.DeleteRange([]byte(""), []byte("a")) + checkRange(1, 999, false) + }) } // BenchDatabaseSuite runs a suite of benchmarks against a KeyValueStore database @@ -438,6 +497,29 @@ func BenchDatabaseSuite(b *testing.B, New func() ethdb.KeyValueStore) { benchBatchWrite(b, keys, vals) }) }) + b.Run("DeleteRange", func(b *testing.B) { + benchDeleteRange := func(b *testing.B, count int) { + db := New() + defer db.Close() + + for i := 0; i < count; i++ { + db.Put([]byte(strconv.Itoa(i)), nil) + } + b.ResetTimer() + b.ReportAllocs() + + db.DeleteRange([]byte("0"), []byte("999999999")) + } + b.Run("DeleteRange100", func(b *testing.B) { + benchDeleteRange(b, 100) + }) + b.Run("DeleteRange1k", func(b *testing.B) { + benchDeleteRange(b, 1000) + }) + b.Run("DeleteRange10k", func(b *testing.B) { + benchDeleteRange(b, 10000) + }) + }) } func iterateKeys(it ethdb.Iterator) []string { diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index 24925a4f04..ce7d823561 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -21,6 +21,7 @@ package leveldb import ( + "bytes" "fmt" "sync" "time" @@ -206,6 +207,36 @@ func (db *Database) Delete(key []byte) error { return db.db.Delete(key, nil) } +var ErrTooManyKeys = errors.New("too many keys in deleted range") + +// DeleteRange deletes all of the keys (and values) in the range [start,end) +// (inclusive on start, exclusive on end). +// Note that this is a fallback implementation as leveldb does not natively +// support range deletion. It can be slow and therefore the number of deleted +// keys is limited in order to avoid blocking for a very long time. +// ErrTooManyKeys is returned if the range has only been partially deleted. +// In this case the caller can repeat the call until it finally succeeds. +func (db *Database) DeleteRange(start, end []byte) error { + batch := db.NewBatch() + it := db.NewIterator(nil, start) + defer it.Release() + + var count int + for it.Next() && bytes.Compare(end, it.Key()) > 0 { + count++ + if count > 10000 { // should not block for more than a second + if err := batch.Write(); err != nil { + return err + } + return ErrTooManyKeys + } + if err := batch.Delete(it.Key()); err != nil { + return err + } + } + return batch.Write() +} + // NewBatch creates a write-only key-value store that buffers changes to its host // database until a final write is called. func (db *Database) NewBatch() ethdb.Batch { diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index 532e0dfe3f..c6fba39cfd 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -18,6 +18,7 @@ package memorydb import ( + "bytes" "errors" "sort" "strings" @@ -121,6 +122,20 @@ func (db *Database) Delete(key []byte) error { return nil } +// DeleteRange deletes all of the keys (and values) in the range [start,end) +// (inclusive on start, exclusive on end). +func (db *Database) DeleteRange(start, end []byte) error { + it := db.NewIterator(nil, start) + defer it.Release() + + for it.Next() && bytes.Compare(end, it.Key()) > 0 { + if err := db.Delete(it.Key()); err != nil { + return err + } + } + return nil +} + // NewBatch creates a write-only key-value store that buffers changes to its host // database until a final write is called. func (db *Database) NewBatch() ethdb.Batch { diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index e2ba9b8c7b..a9151a3bb5 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -335,7 +335,18 @@ func (d *Database) Delete(key []byte) error { if d.closed { return pebble.ErrClosed } - return d.db.Delete(key, nil) + return d.db.Delete(key, d.writeOptions) +} + +// DeleteRange deletes all of the keys (and values) in the range [start,end) +// (inclusive on start, exclusive on end). +func (d *Database) DeleteRange(start, end []byte) error { + d.quitLock.RLock() + defer d.quitLock.RUnlock() + if d.closed { + return pebble.ErrClosed + } + return d.db.DeleteRange(start, end, d.writeOptions) } // NewBatch creates a write-only key-value store that buffers changes to its host diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index d0f018cb01..247a4392db 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -94,6 +94,10 @@ func (db *Database) Delete(key []byte) error { panic("not supported") } +func (db *Database) DeleteRange(start, end []byte) error { + panic("not supported") +} + func (db *Database) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) { panic("not supported") } diff --git a/go.mod b/go.mod index fc469f3e93..1a26321def 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/gofrs/flock v0.8.1 - github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/gofuzz v1.2.0 github.com/google/uuid v1.3.0 @@ -63,7 +63,6 @@ require ( github.com/stretchr/testify v1.9.0 github.com/supranational/blst v0.3.13 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 golang.org/x/crypto v0.22.0 diff --git a/go.sum b/go.sum index 7b88051b5c..19a7b9d25c 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,8 @@ github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -499,8 +499,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= diff --git a/internal/build/file.go b/internal/build/file.go index c159b51892..2d8c993f36 100644 --- a/internal/build/file.go +++ b/internal/build/file.go @@ -16,7 +16,14 @@ package build -import "os" +import ( + "crypto/sha256" + "io" + "os" + "path/filepath" + "sort" + "strings" +) // FileExist checks if a file exists at path. func FileExist(path string) bool { @@ -26,3 +33,70 @@ func FileExist(path string) bool { } return true } + +// HashFiles iterates the provided set of files, computing the hash of each. +func HashFiles(files []string) (map[string][32]byte, error) { + res := make(map[string][32]byte) + for _, filePath := range files { + f, err := os.OpenFile(filePath, os.O_RDONLY, 0666) + if err != nil { + return nil, err + } + hasher := sha256.New() + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + res[filePath] = [32]byte(hasher.Sum(nil)) + } + return res, nil +} + +// HashFolder iterates all files under the given directory, computing the hash +// of each. +func HashFolder(folder string, exlude []string) (map[string][32]byte, error) { + res := make(map[string][32]byte) + err := filepath.WalkDir(folder, func(path string, d os.DirEntry, _ error) error { + // Skip anything that's exluded or not a regular file + for _, skip := range exlude { + if strings.HasPrefix(path, filepath.FromSlash(skip)) { + return filepath.SkipDir + } + } + if !d.Type().IsRegular() { + return nil + } + // Regular file found, hash it + f, err := os.OpenFile(path, os.O_RDONLY, 0666) + if err != nil { + return err + } + hasher := sha256.New() + if _, err := io.Copy(hasher, f); err != nil { + return err + } + res[path] = [32]byte(hasher.Sum(nil)) + return nil + }) + if err != nil { + return nil, err + } + return res, nil +} + +// DiffHashes compares two maps of file hashes and returns the changed files. +func DiffHashes(a map[string][32]byte, b map[string][32]byte) []string { + var updates []string + + for file := range a { + if _, ok := b[file]; !ok || a[file] != b[file] { + updates = append(updates, file) + } + } + for file := range b { + if _, ok := a[file]; !ok { + updates = append(updates, file) + } + } + sort.Strings(updates) + return updates +} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 10d79c85ae..a508b0ca5b 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -29,8 +29,6 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" @@ -51,7 +49,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" - "github.com/tyler-smith/go-bip39" ) // estimateGasErrorRatio is the amount of overestimation eth_estimateGas is @@ -298,344 +295,6 @@ func (api *EthereumAccountAPI) Accounts() []common.Address { return api.am.Accounts() } -// PersonalAccountAPI provides an API to access accounts managed by this node. -// It offers methods to create, (un)lock en list accounts. Some methods accept -// passwords and are therefore considered private by default. -type PersonalAccountAPI struct { - am *accounts.Manager - nonceLock *AddrLocker - b Backend -} - -// NewPersonalAccountAPI creates a new PersonalAccountAPI. -func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI { - return &PersonalAccountAPI{ - am: b.AccountManager(), - nonceLock: nonceLock, - b: b, - } -} - -// ListAccounts will return a list of addresses for accounts this node manages. -func (api *PersonalAccountAPI) ListAccounts() []common.Address { - return api.am.Accounts() -} - -// rawWallet is a JSON representation of an accounts.Wallet interface, with its -// data contents extracted into plain fields. -type rawWallet struct { - URL string `json:"url"` - Status string `json:"status"` - Failure string `json:"failure,omitempty"` - Accounts []accounts.Account `json:"accounts,omitempty"` -} - -// ListWallets will return a list of wallets this node manages. -func (api *PersonalAccountAPI) ListWallets() []rawWallet { - wallets := make([]rawWallet, 0) // return [] instead of nil if empty - for _, wallet := range api.am.Wallets() { - status, failure := wallet.Status() - - raw := rawWallet{ - URL: wallet.URL().String(), - Status: status, - Accounts: wallet.Accounts(), - } - if failure != nil { - raw.Failure = failure.Error() - } - wallets = append(wallets, raw) - } - return wallets -} - -// OpenWallet initiates a hardware wallet opening procedure, establishing a USB -// connection and attempting to authenticate via the provided passphrase. Note, -// the method may return an extra challenge requiring a second open (e.g. the -// Trezor PIN matrix challenge). -func (api *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error { - wallet, err := api.am.Wallet(url) - if err != nil { - return err - } - pass := "" - if passphrase != nil { - pass = *passphrase - } - return wallet.Open(pass) -} - -// DeriveAccount requests an HD wallet to derive a new account, optionally pinning -// it for later reuse. -func (api *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) { - wallet, err := api.am.Wallet(url) - if err != nil { - return accounts.Account{}, err - } - derivPath, err := accounts.ParseDerivationPath(path) - if err != nil { - return accounts.Account{}, err - } - if pin == nil { - pin = new(bool) - } - return wallet.Derive(derivPath, *pin) -} - -// NewAccount will create a new account and returns the address for the new account. -func (api *PersonalAccountAPI) NewAccount(password string) (common.AddressEIP55, error) { - ks, err := fetchKeystore(api.am) - if err != nil { - return common.AddressEIP55{}, err - } - acc, err := ks.NewAccount(password) - if err == nil { - addrEIP55 := common.AddressEIP55(acc.Address) - log.Info("Your new key was generated", "address", addrEIP55.String()) - log.Warn("Please backup your key file!", "path", acc.URL.Path) - log.Warn("Please remember your password!") - return addrEIP55, nil - } - return common.AddressEIP55{}, err -} - -// fetchKeystore retrieves the encrypted keystore from the account manager. -func fetchKeystore(am *accounts.Manager) (*keystore.KeyStore, error) { - if ks := am.Backends(keystore.KeyStoreType); len(ks) > 0 { - return ks[0].(*keystore.KeyStore), nil - } - return nil, errors.New("local keystore not used") -} - -// ImportRawKey stores the given hex encoded ECDSA key into the key directory, -// encrypting it with the passphrase. -func (api *PersonalAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) { - key, err := crypto.HexToECDSA(privkey) - if err != nil { - return common.Address{}, err - } - ks, err := fetchKeystore(api.am) - if err != nil { - return common.Address{}, err - } - acc, err := ks.ImportECDSA(key, password) - return acc.Address, err -} - -// UnlockAccount will unlock the account associated with the given address with -// the given password for duration seconds. If duration is nil it will use a -// default of 300 seconds. It returns an indication if the account was unlocked. -func (api *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) { - // When the API is exposed by external RPC(http, ws etc), unless the user - // explicitly specifies to allow the insecure account unlocking, otherwise - // it is disabled. - if api.b.ExtRPCEnabled() && !api.b.AccountManager().Config().InsecureUnlockAllowed { - return false, errors.New("account unlock with HTTP access is forbidden") - } - - const max = uint64(time.Duration(gomath.MaxInt64) / time.Second) - var d time.Duration - if duration == nil { - d = 300 * time.Second - } else if *duration > max { - return false, errors.New("unlock duration too large") - } else { - d = time.Duration(*duration) * time.Second - } - ks, err := fetchKeystore(api.am) - if err != nil { - return false, err - } - err = ks.TimedUnlock(accounts.Account{Address: addr}, password, d) - if err != nil { - log.Warn("Failed account unlock attempt", "address", addr, "err", err) - } - return err == nil, err -} - -// LockAccount will lock the account associated with the given address when it's unlocked. -func (api *PersonalAccountAPI) LockAccount(addr common.Address) bool { - if ks, err := fetchKeystore(api.am); err == nil { - return ks.Lock(addr) == nil - } - return false -} - -// signTransaction sets defaults and signs the given transaction -// NOTE: the caller needs to ensure that the nonceLock is held, if applicable, -// and release it after the transaction has been submitted to the tx pool -func (api *PersonalAccountAPI) signTransaction(ctx context.Context, args *TransactionArgs, passwd string) (*types.Transaction, error) { - // Look up the wallet containing the requested signer - account := accounts.Account{Address: args.from()} - wallet, err := api.am.Find(account) - if err != nil { - return nil, err - } - // Set some sanity defaults and terminate on failure - if err := args.setDefaults(ctx, api.b, false); err != nil { - return nil, err - } - // Assemble the transaction and sign with the wallet - tx := args.ToTransaction(types.LegacyTxType) - - return wallet.SignTxWithPassphrase(account, passwd, tx, api.b.ChainConfig().ChainID) -} - -// SendTransaction will create a transaction from the given arguments and -// tries to sign it with the key associated with args.From. If the given -// passwd isn't able to decrypt the key it fails. -func (api *PersonalAccountAPI) SendTransaction(ctx context.Context, args TransactionArgs, passwd string) (common.Hash, error) { - if args.Nonce == nil { - // Hold the mutex around signing to prevent concurrent assignment of - // the same nonce to multiple accounts. - api.nonceLock.LockAddr(args.from()) - defer api.nonceLock.UnlockAddr(args.from()) - } - if args.IsEIP4844() { - return common.Hash{}, errBlobTxNotSupported - } - signed, err := api.signTransaction(ctx, &args, passwd) - if err != nil { - log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err) - return common.Hash{}, err - } - return SubmitTransaction(ctx, api.b, signed) -} - -// SignTransaction will create a transaction from the given arguments and -// tries to sign it with the key associated with args.From. If the given passwd isn't -// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast -// to other nodes -func (api *PersonalAccountAPI) SignTransaction(ctx context.Context, args TransactionArgs, passwd string) (*SignTransactionResult, error) { - // No need to obtain the noncelock mutex, since we won't be sending this - // tx into the transaction pool, but right back to the user - if args.From == nil { - return nil, errors.New("sender not specified") - } - if args.Gas == nil { - return nil, errors.New("gas not specified") - } - if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) { - return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas") - } - if args.IsEIP4844() { - return nil, errBlobTxNotSupported - } - if args.Nonce == nil { - return nil, errors.New("nonce not specified") - } - // Before actually signing the transaction, ensure the transaction fee is reasonable. - tx := args.ToTransaction(types.LegacyTxType) - if err := checkTxFee(tx.GasPrice(), tx.Gas(), api.b.RPCTxFeeCap()); err != nil { - return nil, err - } - signed, err := api.signTransaction(ctx, &args, passwd) - if err != nil { - log.Warn("Failed transaction sign attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err) - return nil, err - } - data, err := signed.MarshalBinary() - if err != nil { - return nil, err - } - return &SignTransactionResult{data, signed}, nil -} - -// Sign calculates an Ethereum ECDSA signature for: -// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)) -// -// Note, the produced signature conforms to the secp256k1 curve R, S and V values, -// where the V value will be 27 or 28 for legacy reasons. -// -// The key used to calculate the signature is decrypted with the given password. -// -// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-sign -func (api *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { - // Look up the wallet containing the requested signer - account := accounts.Account{Address: addr} - - wallet, err := api.b.AccountManager().Find(account) - if err != nil { - return nil, err - } - // Assemble sign the data with the wallet - signature, err := wallet.SignTextWithPassphrase(account, passwd, data) - if err != nil { - log.Warn("Failed data sign attempt", "address", addr, "err", err) - return nil, err - } - signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper - return signature, nil -} - -// EcRecover returns the address for the account that was used to create the signature. -// Note, this function is compatible with eth_sign and personal_sign. As such it recovers -// the address of: -// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message}) -// addr = ecrecover(hash, signature) -// -// Note, the signature must conform to the secp256k1 curve R, S and V values, where -// the V value must be 27 or 28 for legacy reasons. -// -// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-ecrecover -func (api *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { - if len(sig) != crypto.SignatureLength { - return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) - } - if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { - return common.Address{}, errors.New("invalid Ethereum signature (V is not 27 or 28)") - } - sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 - - rpk, err := crypto.SigToPub(accounts.TextHash(data), sig) - if err != nil { - return common.Address{}, err - } - return crypto.PubkeyToAddress(*rpk), nil -} - -// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key. -func (api *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) { - wallet, err := api.am.Wallet(url) - if err != nil { - return "", err - } - - entropy, err := bip39.NewEntropy(256) - if err != nil { - return "", err - } - - mnemonic, err := bip39.NewMnemonic(entropy) - if err != nil { - return "", err - } - - seed := bip39.NewSeed(mnemonic, "") - - switch wallet := wallet.(type) { - case *scwallet.Wallet: - return mnemonic, wallet.Initialize(seed) - default: - return "", errors.New("specified wallet does not support initialization") - } -} - -// Unpair deletes a pairing between wallet and geth. -func (api *PersonalAccountAPI) Unpair(ctx context.Context, url string, pin string) error { - wallet, err := api.am.Wallet(url) - if err != nil { - return err - } - - switch wallet := wallet.(type) { - case *scwallet.Wallet: - return wallet.Unpair([]byte(pin)) - default: - return errors.New("specified wallet does not support pairing") - } -} - // BlockChainAPI provides an API to access Ethereum blockchain data. type BlockChainAPI struct { b Backend @@ -1628,9 +1287,18 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH } // Ensure any missing fields are filled, extract the recipient and input data - if err := args.setDefaults(ctx, b, true); err != nil { + if err = args.setFeeDefaults(ctx, b, header); err != nil { return nil, 0, nil, err } + if args.Nonce == nil { + nonce := hexutil.Uint64(db.GetNonce(args.from())) + args.Nonce = &nonce + } + blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) + if err = args.CallDefaults(b.RPCGasCap(), blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil { + return nil, 0, nil, err + } + var to common.Address if args.To != nil { to = *args.To diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index ccc11472b7..82465ca7d7 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -118,9 +118,6 @@ func GetAPIs(apiBackend Backend) []rpc.API { }, { Namespace: "eth", Service: NewEthereumAccountAPI(apiBackend.AccountManager()), - }, { - Namespace: "personal", - Service: NewPersonalAccountAPI(apiBackend, nonceLock), }, } } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index b6346e910d..91e05544dc 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -100,7 +100,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas if err := args.setBlobTxSidecar(ctx); err != nil { return err } - if err := args.setFeeDefaults(ctx, b); err != nil { + if err := args.setFeeDefaults(ctx, b, b.CurrentHeader()); err != nil { return err } @@ -183,8 +183,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas } // setFeeDefaults fills in default fee values for unspecified tx fields. -func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) error { - head := b.CurrentHeader() +func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend, head *types.Header) error { // Sanity check the EIP-4844 fee parameters. if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 { return errors.New("maxFeePerBlobGas, if specified, must be non-zero") diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index a3bf19b686..5f59b491e1 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -238,7 +238,7 @@ func TestSetFeeDefaults(t *testing.T) { t.Fatalf("failed to set fork: %v", err) } got := test.in - err := got.setFeeDefaults(ctx, b) + err := got.setFeeDefaults(ctx, b, b.CurrentHeader()) if err != nil { if test.err == nil { t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err) diff --git a/internal/flags/flags.go b/internal/flags/flags.go index bf62c53adf..1f6be3d3d3 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -17,7 +17,6 @@ package flags import ( - "encoding" "errors" "flag" "fmt" @@ -122,119 +121,6 @@ func (f *DirectoryFlag) GetDefaultText() string { return f.GetValue() } -type TextMarshaler interface { - encoding.TextMarshaler - encoding.TextUnmarshaler -} - -// textMarshalerVal turns a TextMarshaler into a flag.Value -type textMarshalerVal struct { - v TextMarshaler -} - -func (v textMarshalerVal) String() string { - if v.v == nil { - return "" - } - text, _ := v.v.MarshalText() - return string(text) -} - -func (v textMarshalerVal) Set(s string) error { - return v.v.UnmarshalText([]byte(s)) -} - -var ( - _ cli.Flag = (*TextMarshalerFlag)(nil) - _ cli.RequiredFlag = (*TextMarshalerFlag)(nil) - _ cli.VisibleFlag = (*TextMarshalerFlag)(nil) - _ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil) - _ cli.CategorizableFlag = (*TextMarshalerFlag)(nil) -) - -// TextMarshalerFlag wraps a TextMarshaler value. -type TextMarshalerFlag struct { - Name string - - Category string - DefaultText string - Usage string - - Required bool - Hidden bool - HasBeenSet bool - - Value TextMarshaler - - Aliases []string - EnvVars []string -} - -// For cli.Flag: - -func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } -func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet } -func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) } - -func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error { - for _, envVar := range f.EnvVars { - envVar = strings.TrimSpace(envVar) - if value, found := syscall.Getenv(envVar); found { - if err := f.Value.UnmarshalText([]byte(value)); err != nil { - return fmt.Errorf("could not parse %q from environment variable %q for flag %s: %s", value, envVar, f.Name, err) - } - f.HasBeenSet = true - break - } - } - eachName(f, func(name string) { - set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) - }) - return nil -} - -// For cli.RequiredFlag: - -func (f *TextMarshalerFlag) IsRequired() bool { return f.Required } - -// For cli.VisibleFlag: - -func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden } - -// For cli.CategorizableFlag: - -func (f *TextMarshalerFlag) GetCategory() string { return f.Category } - -// For cli.DocGenerationFlag: - -func (f *TextMarshalerFlag) TakesValue() bool { return true } -func (f *TextMarshalerFlag) GetUsage() string { return f.Usage } -func (f *TextMarshalerFlag) GetEnvVars() []string { return f.EnvVars } - -func (f *TextMarshalerFlag) GetValue() string { - t, err := f.Value.MarshalText() - if err != nil { - return "(ERR: " + err.Error() + ")" - } - return string(t) -} - -func (f *TextMarshalerFlag) GetDefaultText() string { - if f.DefaultText != "" { - return f.DefaultText - } - return f.GetValue() -} - -// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set. -func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { - val := ctx.Generic(name) - if val == nil { - return nil - } - return val.(textMarshalerVal).v -} - var ( _ cli.Flag = (*BigFlag)(nil) _ cli.RequiredFlag = (*BigFlag)(nil) diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go index 32be3d11a7..fd706869f1 100644 --- a/internal/flags/helpers.go +++ b/internal/flags/helpers.go @@ -48,15 +48,6 @@ func NewApp(usage string) *cli.App { return app } -// Merge merges the given flag slices. -func Merge(groups ...[]cli.Flag) []cli.Flag { - var ret []cli.Flag - for _, group := range groups { - ret = append(ret, group...) - } - return ret -} - var migrationApplied = map[*cli.Command]struct{}{} // MigrateGlobalFlags makes all global flag values available in the @@ -265,9 +256,6 @@ func AutoEnvVars(flags []cli.Flag, prefix string) { case *BigFlag: flag.EnvVars = append(flag.EnvVars, envvar) - case *TextMarshalerFlag: - flag.EnvVars = append(flag.EnvVars, envvar) - case *DirectoryFlag: flag.EnvVars = append(flag.EnvVars, envvar) } diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 927ebc2ef0..0c346bbf79 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -18,16 +18,15 @@ package web3ext var Modules = map[string]string{ - "admin": AdminJs, - "clique": CliqueJs, - "debug": DebugJs, - "eth": EthJs, - "miner": MinerJs, - "net": NetJs, - "personal": PersonalJs, - "rpc": RpcJs, - "txpool": TxpoolJs, - "dev": DevJs, + "admin": AdminJs, + "clique": CliqueJs, + "debug": DebugJs, + "eth": EthJs, + "miner": MinerJs, + "net": NetJs, + "rpc": RpcJs, + "txpool": TxpoolJs, + "dev": DevJs, } const CliqueJs = ` @@ -658,62 +657,6 @@ web3._extend({ }); ` -const PersonalJs = ` -web3._extend({ - property: 'personal', - methods: [ - new web3._extend.Method({ - name: 'importRawKey', - call: 'personal_importRawKey', - params: 2 - }), - new web3._extend.Method({ - name: 'sign', - call: 'personal_sign', - params: 3, - inputFormatter: [null, web3._extend.formatters.inputAddressFormatter, null] - }), - new web3._extend.Method({ - name: 'ecRecover', - call: 'personal_ecRecover', - params: 2 - }), - new web3._extend.Method({ - name: 'openWallet', - call: 'personal_openWallet', - params: 2 - }), - new web3._extend.Method({ - name: 'deriveAccount', - call: 'personal_deriveAccount', - params: 3 - }), - new web3._extend.Method({ - name: 'signTransaction', - call: 'personal_signTransaction', - params: 2, - inputFormatter: [web3._extend.formatters.inputTransactionFormatter, null] - }), - new web3._extend.Method({ - name: 'unpair', - call: 'personal_unpair', - params: 2 - }), - new web3._extend.Method({ - name: 'initializeWallet', - call: 'personal_initializeWallet', - params: 1 - }) - ], - properties: [ - new web3._extend.Property({ - name: 'listWallets', - getter: 'personal_listWallets' - }), - ] -}) -` - const RpcJs = ` web3._extend({ property: 'rpc', diff --git a/log/logger_test.go b/log/logger_test.go index f1a9a93bce..3ec6d2e19c 100644 --- a/log/logger_test.go +++ b/log/logger_test.go @@ -7,7 +7,6 @@ import ( "io" "log/slog" "math/big" - "os" "strings" "testing" "time" @@ -70,7 +69,7 @@ func TestJSONHandler(t *testing.T) { } func BenchmarkTraceLogging(b *testing.B) { - SetDefault(NewLogger(NewTerminalHandler(os.Stderr, true))) + SetDefault(NewLogger(NewTerminalHandler(io.Discard, true))) b.ResetTimer() for i := 0; i < b.N; i++ { Trace("a message", "v", i) diff --git a/metrics/sample_test.go b/metrics/sample_test.go index 4227b43ef7..c855671ae2 100644 --- a/metrics/sample_test.go +++ b/metrics/sample_test.go @@ -3,7 +3,6 @@ package metrics import ( "math" "math/rand" - "runtime" "testing" "time" ) @@ -27,6 +26,7 @@ func BenchmarkCompute1000(b *testing.B) { SampleVariance(mean, s) } } + func BenchmarkCompute1000000(b *testing.B) { s := make([]int64, 1000000) var sum int64 @@ -40,28 +40,6 @@ func BenchmarkCompute1000000(b *testing.B) { SampleVariance(mean, s) } } -func BenchmarkCopy1000(b *testing.B) { - s := make([]int64, 1000) - for i := 0; i < len(s); i++ { - s[i] = int64(i) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - sCopy := make([]int64, len(s)) - copy(sCopy, s) - } -} -func BenchmarkCopy1000000(b *testing.B) { - s := make([]int64, 1000000) - for i := 0; i < len(s); i++ { - s[i] = int64(i) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - sCopy := make([]int64, len(s)) - copy(sCopy, s) - } -} func BenchmarkExpDecaySample257(b *testing.B) { benchmarkSample(b, NewExpDecaySample(257, 0.015)) @@ -237,17 +215,9 @@ func TestUniformSampleStatistics(t *testing.T) { } func benchmarkSample(b *testing.B, s Sample) { - var memStats runtime.MemStats - runtime.ReadMemStats(&memStats) - pauseTotalNs := memStats.PauseTotalNs - b.ResetTimer() for i := 0; i < b.N; i++ { s.Update(1) } - b.StopTimer() - runtime.GC() - runtime.ReadMemStats(&memStats) - b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N) } func testExpDecaySampleStatistics(t *testing.T, s SampleSnapshot) { diff --git a/node/database.go b/node/database.go new file mode 100644 index 0000000000..e3ccb91066 --- /dev/null +++ b/node/database.go @@ -0,0 +1,111 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package node + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/leveldb" + "github.com/ethereum/go-ethereum/ethdb/pebble" + "github.com/ethereum/go-ethereum/log" +) + +// openOptions contains the options to apply when opening a database. +// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used. +type openOptions struct { + Type string // "leveldb" | "pebble" + Directory string // the datadir + AncientsDirectory string // the ancients-dir + Namespace string // the namespace for database relevant metrics + Cache int // the capacity(in megabytes) of the data caching + Handles int // number of files to be open simultaneously + ReadOnly bool +} + +// openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also +// integrates it with a freezer database -- if the AncientDir option has been +// set on the provided OpenOptions. +// The passed o.AncientDir indicates the path of root ancient directory where +// the chain freezer can be opened. +func openDatabase(o openOptions) (ethdb.Database, error) { + kvdb, err := openKeyValueDatabase(o) + if err != nil { + return nil, err + } + if len(o.AncientsDirectory) == 0 { + return kvdb, nil + } + frdb, err := rawdb.NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly) + if err != nil { + kvdb.Close() + return nil, err + } + return frdb, nil +} + +// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. +// +// type == null type != null +// +---------------------------------------- +// db is non-existent | pebble default | specified type +// db is existent | from db | specified type (if compatible) +func openKeyValueDatabase(o openOptions) (ethdb.Database, error) { + // Reject any unsupported database type + if len(o.Type) != 0 && o.Type != rawdb.DBLeveldb && o.Type != rawdb.DBPebble { + return nil, fmt.Errorf("unknown db.engine %v", o.Type) + } + // Retrieve any pre-existing database's type and use that or the requested one + // as long as there's no conflict between the two types + existingDb := rawdb.PreexistingDatabase(o.Directory) + if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { + return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) + } + if o.Type == rawdb.DBPebble || existingDb == rawdb.DBPebble { + log.Info("Using pebble as the backing database") + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) + } + if o.Type == rawdb.DBLeveldb || existingDb == rawdb.DBLeveldb { + log.Info("Using leveldb as the backing database") + return newLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) + } + // No pre-existing database, no user-requested one either. Default to Pebble. + log.Info("Defaulting to pebble as the backing database") + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) +} + +// newLevelDBDatabase creates a persistent key-value database without a freezer +// moving immutable chain segments into cold storage. +func newLevelDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { + db, err := leveldb.New(file, cache, handles, namespace, readonly) + if err != nil { + return nil, err + } + log.Info("Using LevelDB as the backing database") + return rawdb.NewDatabase(db), nil +} + +// newPebbleDBDatabase creates a persistent key-value database without a freezer +// moving immutable chain segments into cold storage. +func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { + db, err := pebble.New(file, cache, handles, namespace, readonly) + if err != nil { + return nil, err + } + return rawdb.NewDatabase(db), nil +} diff --git a/node/node.go b/node/node.go index 633f88f058..92c0c35607 100644 --- a/node/node.go +++ b/node/node.go @@ -375,25 +375,13 @@ func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) { // startup. It's not meant to be called at any time afterwards as it makes certain // assumptions about the state of the node. func (n *Node) startRPC() error { - // Filter out personal api - var apis []rpc.API - for _, api := range n.rpcAPIs { - if api.Namespace == "personal" { - if n.config.EnablePersonal { - log.Warn("Deprecated personal namespace activated") - } else { - continue - } - } - apis = append(apis, api) - } - if err := n.startInProc(apis); err != nil { + if err := n.startInProc(n.rpcAPIs); err != nil { return err } // Configure IPC. if n.ipc.endpoint != "" { - if err := n.ipc.start(apis); err != nil { + if err := n.ipc.start(n.rpcAPIs); err != nil { return err } } @@ -723,7 +711,7 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r if n.config.DataDir == "" { db = rawdb.NewMemoryDatabase() } else { - db, err = rawdb.Open(rawdb.OpenOptions{ + db, err = openDatabase(openOptions{ Type: n.config.DBEngine, Directory: n.ResolvePath(name), Namespace: namespace, @@ -732,7 +720,6 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r ReadOnly: readonly, }) } - if err == nil { db = n.wrapDatabase(db) } @@ -755,7 +742,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient if n.config.DataDir == "" { db, err = rawdb.NewDatabaseWithFreezer(memorydb.New(), "", namespace, readonly) } else { - db, err = rawdb.Open(rawdb.OpenOptions{ + db, err = openDatabase(openOptions{ Type: n.config.DBEngine, Directory: n.ResolvePath(name), AncientsDirectory: n.ResolveAncient(name, ancient), @@ -765,7 +752,6 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient ReadOnly: readonly, }) } - if err == nil { db = n.wrapDatabase(db) } diff --git a/oss-fuzz.sh b/oss-fuzz.sh index 7993dc9c64..50491b9155 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -220,6 +220,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \ Fuzz fuzzSecp256k1\ $repo/tests/fuzzers/secp256k1/secp_test.go +compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \ + FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \ + $repo/eth/protocols/eth/handler_test.go + #compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool #compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty diff --git a/p2p/netutil/addrutil_test.go b/p2p/netutil/addrutil_test.go new file mode 100644 index 0000000000..0abbabb54b --- /dev/null +++ b/p2p/netutil/addrutil_test.go @@ -0,0 +1,140 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package netutil + +import ( + "net" + "net/netip" + "path/filepath" + "testing" +) + +// customNetAddr is a custom implementation of net.Addr for testing purposes. +type customNetAddr struct{} + +func (c *customNetAddr) Network() string { return "custom" } +func (c *customNetAddr) String() string { return "custom" } + +func TestAddrAddr(t *testing.T) { + tempDir := t.TempDir() + tests := []struct { + name string + addr net.Addr + want netip.Addr + }{ + { + name: "IPAddr IPv4", + addr: &net.IPAddr{IP: net.ParseIP("192.0.2.1")}, + want: netip.MustParseAddr("192.0.2.1"), + }, + { + name: "IPAddr IPv6", + addr: &net.IPAddr{IP: net.ParseIP("2001:db8::1")}, + want: netip.MustParseAddr("2001:db8::1"), + }, + { + name: "TCPAddr IPv4", + addr: &net.TCPAddr{IP: net.ParseIP("192.0.2.1"), Port: 8080}, + want: netip.MustParseAddr("192.0.2.1"), + }, + { + name: "TCPAddr IPv6", + addr: &net.TCPAddr{IP: net.ParseIP("2001:db8::1"), Port: 8080}, + want: netip.MustParseAddr("2001:db8::1"), + }, + { + name: "UDPAddr IPv4", + addr: &net.UDPAddr{IP: net.ParseIP("192.0.2.1"), Port: 8080}, + want: netip.MustParseAddr("192.0.2.1"), + }, + { + name: "UDPAddr IPv6", + addr: &net.UDPAddr{IP: net.ParseIP("2001:db8::1"), Port: 8080}, + want: netip.MustParseAddr("2001:db8::1"), + }, + { + name: "Unsupported Addr type", + addr: &net.UnixAddr{Name: filepath.Join(tempDir, "test.sock"), Net: "unix"}, + want: netip.Addr{}, + }, + { + name: "Nil input", + addr: nil, + want: netip.Addr{}, + }, + { + name: "Custom net.Addr implementation", + addr: &customNetAddr{}, + want: netip.Addr{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := AddrAddr(tt.addr); got != tt.want { + t.Errorf("AddrAddr() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIPToAddr(t *testing.T) { + tests := []struct { + name string + ip net.IP + want netip.Addr + }{ + { + name: "IPv4", + ip: net.ParseIP("192.0.2.1"), + want: netip.MustParseAddr("192.0.2.1"), + }, + { + name: "IPv6", + ip: net.ParseIP("2001:db8::1"), + want: netip.MustParseAddr("2001:db8::1"), + }, + { + name: "Invalid IP", + ip: net.IP{1, 2, 3}, + want: netip.Addr{}, + }, + { + name: "Invalid IP (5 octets)", + ip: net.IP{192, 0, 2, 1, 1}, + want: netip.Addr{}, + }, + { + name: "IPv4-mapped IPv6", + ip: net.ParseIP("::ffff:192.0.2.1"), + want: netip.MustParseAddr("192.0.2.1"), + }, + { + name: "Nil input", + ip: nil, + want: netip.Addr{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IPToAddr(tt.ip); got != tt.want { + t.Errorf("IPToAddr() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/signer/core/apitypes/signed_data_internal_test.go b/signer/core/apitypes/signed_data_internal_test.go index 8b4a839c1d..1a14b35ef2 100644 --- a/signer/core/apitypes/signed_data_internal_test.go +++ b/signer/core/apitypes/signed_data_internal_test.go @@ -18,12 +18,18 @@ package apitypes import ( "bytes" + "encoding/json" + "fmt" "math/big" + "os" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestBytesPadding(t *testing.T) { @@ -244,45 +250,42 @@ func TestConvertAddressDataToSlice(t *testing.T) { func TestTypedDataArrayValidate(t *testing.T) { t.Parallel() - typedData := TypedData{ - Types: Types{ - "BulkOrder": []Type{ - // Should be able to accept fixed size arrays - {Name: "tree", Type: "OrderComponents[2][2]"}, - }, - "OrderComponents": []Type{ - {Name: "offerer", Type: "address"}, - {Name: "amount", Type: "uint8"}, - }, - "EIP712Domain": []Type{ - {Name: "name", Type: "string"}, - {Name: "version", Type: "string"}, - {Name: "chainId", Type: "uint8"}, - {Name: "verifyingContract", Type: "address"}, - }, - }, - PrimaryType: "BulkOrder", - Domain: TypedDataDomain{ - VerifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", - }, - Message: TypedDataMessage{}, + type testDataInput struct { + Name string `json:"name"` + Domain TypedDataDomain `json:"domain"` + PrimaryType string `json:"primaryType"` + Types Types `json:"types"` + Message TypedDataMessage `json:"data"` + Digest string `json:"digest"` } + fc, err := os.ReadFile("./testdata/typed-data.json") + require.NoError(t, err, "error reading test data file") - if err := typedData.validate(); err != nil { - t.Errorf("expected typed data to pass validation, got: %v", err) - } + var tests []testDataInput + err = json.Unmarshal(fc, &tests) + require.NoError(t, err, "error unmarshalling test data file contents") - // Should be able to accept dynamic arrays - typedData.Types["BulkOrder"][0].Type = "OrderComponents[]" + for _, tc := range tests { + t.Run(tc.Name, func(t *testing.T) { + t.Parallel() - if err := typedData.validate(); err != nil { - t.Errorf("expected typed data to pass validation, got: %v", err) - } + td := TypedData{ + Types: tc.Types, + PrimaryType: tc.PrimaryType, + Domain: tc.Domain, + Message: tc.Message, + } - // Should be able to accept standard types - typedData.Types["BulkOrder"][0].Type = "OrderComponents" + domainSeparator, tErr := td.HashStruct("EIP712Domain", td.Domain.Map()) + assert.NoError(t, tErr, "failed to hash domain separator: %v", tErr) - if err := typedData.validate(); err != nil { - t.Errorf("expected typed data to pass validation, got: %v", err) + messageHash, tErr := td.HashStruct(td.PrimaryType, td.Message) + assert.NoError(t, tErr, "failed to hash message: %v", tErr) + + digest := crypto.Keccak256Hash([]byte(fmt.Sprintf("%s%s%s", "\x19\x01", string(domainSeparator), string(messageHash)))) + assert.Equal(t, tc.Digest, digest.String(), "digest doesn't not match") + + assert.NoError(t, td.validate(), "validation failed", tErr) + }) } } diff --git a/signer/core/apitypes/testdata/typed-data.json b/signer/core/apitypes/testdata/typed-data.json new file mode 100644 index 0000000000..f77f72e5eb --- /dev/null +++ b/signer/core/apitypes/testdata/typed-data.json @@ -0,0 +1,6089 @@ +[ + { + "name": "random-0", + "domain": { + "name": "Moo é🚀ooéééMooooM🚀 o🚀🚀o M oM🚀éo 🚀🚀🚀🚀éoMoéo🚀o", + "version": "28.44.13" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0xdce44ca98616ee629199215ae5401c97040664637c48" + }, + "encoded": "0xcdf7d44b9a42bfc5a90b1624215e30c70425b44f1c62f94244b32551826d2dd995cff8fcf943ffa581b017b61b02703628c843642652c382dd15c9a471fe28d9", + "digest": "0xf1a2769507736a9aa306204169e6862f4416e055035d7d2cc9ab6f1921604905" + }, + { + "name": "random-1", + "domain": { + "name": "Moo é🚀éoMo🚀 oé🚀🚀🚀MéooMéooo éo oé 🚀M🚀 🚀 o", + "version": "22.43.44", + "chainId": 1268, + "salt": "0x6ebb306942854acbb10134c9dee015937042c39da2ee124eb926ad77df52dbe0" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes11" + }, + { + "name": "param4", + "type": "bytes" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": "0x2364d8559a1777b684a9121d132c4b4237e2534bd5a0", + "param3": "0x90166c1d5cf7f1be5e4535", + "param4": "0x0f6c35f4b0fa348c603ee0070c8f4f971805c4d9d2ddb8acb82e806e1f4b2c1bc500e41b882213648af39dd4a29d303a31f68476cf803ef8c9024509b2f164", + "param5": "Moo é🚀MoM🚀éoMMooM🚀ooéM Mééo" + }, + "encoded": "0xda8977a44f657114a662894ef7761924845f9e7530ec21622e1a6d5526de0d1ec611cbc6650fb22a47f359606312a4412acbc7b648fa712da2d0e65a00e44f8990166c1d5cf7f1be5e453500000000000000000000000000000000000000000082609c13a160a82264f3293420c066ad847fc2c658862f6282c13848e7c2bfa3c422f8f8d57a0d73e4448edcb393d45cd1969652b199e87011a5c54171f7a548", + "digest": "0xdca475186d6626bdd727f5a216758f6351c56b36ae77683f3b381c5b296d1099" + }, + { + "name": "random-2", + "domain": { + "verifyingContract": "0xb98ccb3b2f1843cdd391295779890c162f2833ea" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "int32" + }, + { + "name": "param3", + "type": "string[3]" + }, + { + "name": "param5", + "type": "address" + } + ] + }, + "data": { + "param2": "-828619503", + "param3": [ + "Moo é🚀o🚀oo🚀o ooééM M🚀éoééoMMooo🚀éoooéooMéoéMM oé🚀Mé éé", + "Moo é🚀o🚀M ééé🚀 o oMéoMéM o🚀oMoo🚀é🚀 é é🚀M🚀é Mooééo🚀é", + "Moo é🚀 🚀oooéé o🚀oéMooM🚀🚀 oo M🚀M🚀ooMoMoooé🚀M🚀 🚀M🚀🚀🚀éM" + ], + "param5": "0xd5cf50b584016c19732d845cc9c8d3a43ce41362" + }, + "encoded": "0x67fb8e8c0399ea6a53c5be40a9cc57f8682c0e4887d4e92733d7e77e358fb473ffffffffffffffffffffffffffffffffffffffffffffffffffffffffce9c451142865dc16e0353e94811b8b8df478cf0a5714219aa578dd5881f162ef224cb2c000000000000000000000000d5cf50b584016c19732d845cc9c8d3a43ce41362", + "digest": "0x6c32dc60957ea693087837ae10ba9d9e31febf7a0c2ed00f6b57ac02f4d4b37e" + }, + { + "name": "random-3", + "domain": { + "name": "Moo é🚀M oMoo🚀éoo🚀ooo ooéééo🚀éMoo🚀o o oo 🚀oooM ", + "version": "31.7.9", + "chainId": 793 + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "string" + } + ] + }, + "data": { + "param2": "0x2302fce888f2dc9d6ec2b3d3fc06aa212ec06b07f4035f64fcc58f1e178bee", + "param3": "0xb1d7e299", + "param4": "Moo é🚀 ooo🚀🚀o🚀ooéé oé" + }, + "encoded": "0xb294e832799f75dfe653c1529c1464de82ad988a243b4cd2dad2e8231ce02ac8f98e5673d8c98474e896eb51f7710e3096ac480f57c343aa4b6940f14ba864cfc9825dc5acadefe8114be8b3b40ff1735c38ce7a2bd1af26b8f896f448f71b2d92ca886c2f1728e95855af472331fec2b8cbcb28901e0b5e5e7c0fcdfb82df75", + "digest": "0x29afbb5d796c6d1b9e79071d245061a8d284ffabf3138483d13736a61780ccdd" + }, + { + "name": "random-4", + "domain": { + "name": "Moo é🚀oo ", + "chainId": 1190, + "salt": "0x1f37012abd2887491b2dc97283565221433f671fe1e39aa52501bfb6aa8b93c3" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes10" + }, + { + "name": "param3", + "type": "string[1]" + }, + { + "name": "param5", + "type": "bytes27" + } + ] + }, + "data": { + "param2": "0x9bb8048b699386b24539", + "param3": [ + "Moo é🚀 éo🚀oMMéoo ooM🚀ooMo oMoéoéé oo 🚀oMMé🚀🚀ooooMéMoé 🚀oéooooéM" + ], + "param5": "0x87522812e1a8337045160896fb3e61f869b4154b737a082b3dfeb7" + }, + "encoded": "0xd6c2b6107cccf91b779f9954f2110d1b60cbc77e11fba6eaea01e944fd9cf1779bb8048b699386b2453900000000000000000000000000000000000000000000efd410fd47fe79acfda00711d702442f7cf6312190754acb4613b1c2aca0dec187522812e1a8337045160896fb3e61f869b4154b737a082b3dfeb70000000000", + "digest": "0xf4f1328085f730d46a20fa49f6e7ac254f35447282c91a7530242a3a14474116" + }, + { + "name": "random-5", + "domain": { + "version": "7.9.9" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "int224" + } + ] + }, + "data": { + "param2": "0x2f89d3d2d83f46d0147efc081e3a3f1012406c69", + "param3": "-1117663001459922125771233981131891587208615016687544676675378200714" + }, + "encoded": "0xded571df13886530cfad8a76abc529603094afe8d4763a3c714a8a86241c16b10000000000000000000000002f89d3d2d83f46d0147efc081e3a3f1012406c69fffffffff5631c9b4cdb160013e3cedb0d8e15ad26177e422ad39cfdf0483f76", + "digest": "0x1f4896667fd2210e54760bd5f00b964447be3c0a20d9d64f8324821a44dbe9a8" + }, + { + "name": "random-6", + "domain": { + "name": "Moo é🚀", + "verifyingContract": "0x501809f11ffb4ec90411dca095641b87f3229df9", + "salt": "0x613b2e73477c57fc4e28b4c06f436f9825b5aa4d839c3d07a89179ef2774f76e" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "address" + } + ] + }, + "data": { + "param2": "0x85a6f822054409e83460b9da070ce6c48843e4793c5720ad69102099b4a52978a90e32242a8b7df6fc70ddc8f6056c1df4585c727e4dac", + "param3": "0xac0ca9396225af9df605b4d3a3273d0c075c5dc2254b1d69fabcffb9cb191cb7253e55c547f8627a79", + "param4": false, + "param5": "0x083e80e0d94dbb979ce2c44a2c746ecfa1fca9f1" + }, + "encoded": "0xe5b40a524086d02c883ca8067a58dc9b784c44542de0bc37d5769a0dbeca31dfdcd5d1450de8a86034460ed9842ded280ce4faa8919759337539cca0876a7da6c95d6f26124f374b1007778a627aabfe799b09620b14cd82e0ce2dc27b5b4aba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083e80e0d94dbb979ce2c44a2c746ecfa1fca9f1", + "digest": "0x77f779953f0ad6e059d13f714999b8f2e0916f3c4263db272606efa34c18c4eb" + }, + { + "name": "random-7", + "domain": { + "version": "29.42.9", + "verifyingContract": "0xa2f34b603e4ee3de26502a40c8dc33886c1bb7e0" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes[2]" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": "0xb7788f98b3107c588bee30ccc844e129a7772df540c3193239df", + "param3": [ + "0xe85938a8c29ab7b82264cc2e0822673fe17637364d6b384eb49f89e1adf61a11", + "0x10ec7831da9a49dbf10818" + ], + "param5": "Moo é🚀ooooM🚀 oMééM éé🚀🚀oMé 🚀 é éé" + }, + "encoded": "0xcf3bbe1dcf56fb9655824a3f90f1953ea791787867fb34004275382e4f47a2bb1c88290b2a99cb28a10db644f89833ecc797c9d2d9c142a5b633939e1c8819bc58bf6d520785f87bcfe82d2eab0d7ba35d93478d835dd7de28c44e0dccc8619c45dd7a5ec721fb2064788313d7807140e33459ce08dbf30bceb4d093096db6f3", + "digest": "0x446d1bab14cbf7b0bc6dad1cf30aeb89585df7150e0a19d809ea23c7bc4d0908" + }, + { + "name": "random-8", + "domain": { + "name": "Moo é🚀oo Moé🚀oMM🚀🚀o oéoéooé é" + }, + "primaryType": "Struct12", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + } + ], + "Struct10": [ + { + "name": "param4", + "type": "int40[3]" + }, + { + "name": "param6", + "type": "string" + }, + { + "name": "param7", + "type": "int152[1]" + }, + { + "name": "param9", + "type": "bytes10" + } + ], + "Struct12": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "Struct10" + }, + { + "name": "param11", + "type": "bytes7" + } + ] + }, + "data": { + "param11": "0x35c68a72cc994a", + "param2": "Moo é🚀ooM🚀 MooMoo oM🚀M🚀🚀oMoo🚀éoéMoooM ", + "param3": { + "param4": [ + "-502183273437", + "-181945777056", + "-454055253301" + ], + "param6": "Moo é🚀 🚀ooMo🚀Mo Mé MééM🚀éo🚀é 🚀é éé oééé🚀🚀ooéM🚀🚀o", + "param7": [ + "2830948558399330007235690811772897616211515216" + ], + "param9": "0x31ee08b2239ded1369a2" + } + }, + "encoded": "0xb791414599e8b56f4b0391cb8b4d422bcf755603c5ddd6e103893a71ceba46241f5744b35eb3f3ef0a6e8cab59bf3b8b6a6691dd30ebf8939d36dd52b98acaea10c8cdc69e509a68998f2d5e30e095c9849a68b644b21c3dfcfd30ffc502114735c68a72cc994a00000000000000000000000000000000000000000000000000", + "digest": "0x8694ca7a01c36837d2449232907509801ed64e23dc023fcf736315f5eec1053c" + }, + { + "name": "random-9", + "domain": { + "chainId": 437 + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "bytes8" + } + ] + }, + "data": { + "param2": "Moo é🚀🚀M🚀🚀oé Mo ééMo", + "param3": "0xc4737eceba804e84" + }, + "encoded": "0x979ff42839e8663fdf777083b1648c659b691503a28c6a2910d1d7cd162a3aa17bcd164aa59dabcd7c3be7e32492e7fe4a48e70aee5b964137249e361ebc9a41c4737eceba804e84000000000000000000000000000000000000000000000000", + "digest": "0x32e8f650680b00d4b5515e9de9684995c3245b4761046780b33ef9f6ee05362c" + }, + { + "name": "random-10", + "domain": { + "name": "Moo é🚀 o éé Mé🚀éoo 🚀oéM MM🚀é 🚀éMM🚀éMo M oé🚀MMoo é o é 🚀o🚀ooo", + "version": "45.0.46" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "bytes2" + }, + { + "name": "param3", + "type": "address[3]" + }, + { + "name": "param5", + "type": "int8[3][1]" + } + ] + }, + "data": { + "param2": "0xdc77", + "param3": [ + "0x6fe07a398b47ee3d064460f74fb00b8454577d8f", + "0x4489956d5c84285dd2337de059733fd7caff5e3b", + "0xc562d2e19f4c8416f7adcdecacb47c7f3b429a18" + ], + "param5": [ + [ + "-10", + "-97", + "-22" + ] + ] + }, + "encoded": "0x9ca5f56281a4926287c930891cd4218d7e9d7e5bd6f8f35ca52190b2a54c5989dc7700000000000000000000000000000000000000000000000000000000000050b4d189d5c6d2e1fe9f152de6692da9fc34d41324dab5ced8a52397fa5ebfff5bb6e21b54c9b4e7f21b6cfe5999121f5dec6f1101cd5e0fb73a634001e5f2ea", + "digest": "0x59c2336278c748fca8889f8b98d6c386f1badb72f28668a5c760c3aff20a922a" + }, + { + "name": "random-11", + "domain": { + "salt": "0x60a7ef7f891f64c8c659e7b3f448e0e82939483d467088aae991d873c2371932" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "int88" + } + ] + }, + "data": { + "param2": "-109147385638873134356016336" + }, + "encoded": "0x22f16ecbd883f7cd7823cc5ec368999cf3bf08546bbd7c708ca231a54353cb86ffffffffffffffffffffffffffffffffffffffffffa5b7245e537649c9e75330", + "digest": "0x1c1c3e593358ec697d2f26c497abc72af68d617441a9825b6cb7c79e92bb2a01" + }, + { + "name": "random-12", + "domain": { + "name": "Moo é🚀oéé🚀🚀🚀o🚀é MoéoMooooo🚀 MMo Moo 🚀 ééo", + "version": "13.24.35", + "salt": "0x9f4a7cb7e30809076edbb99bcbc310ec27d7a563cbc24cddd0a2ae6d275677ef" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "address" + } + ] + }, + "data": { + "param2": "0xff4d2657142a58d3cc787e089ca7f20a6b66776e" + }, + "encoded": "0x98edda54668461e736d24a4033f2d11540bceac48ea14c7da0fea73b8b9a55db000000000000000000000000ff4d2657142a58d3cc787e089ca7f20a6b66776e", + "digest": "0xf73e0203cb874ce615b0ceb1c8c8358eb44719bbab11ebe963e00a914434ce62" + }, + { + "name": "random-13", + "domain": { + "name": "Moo é🚀", + "chainId": 348, + "salt": "0xc70f3b18e636eee4a800a307d1b38bf2cf6fbb923a5c3ae3b14becbfc2ce1f9b" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "Moo é🚀🚀oé MoMMéo", + "param3": "0xc3e57dbac4c0a82334953baa752df10cffd5a75a2edcbe00c7f2" + }, + "encoded": "0x4d0024736263d208aca6e84c7bb7336060a12a4693f70ea14290ed4308d052e5eb273f8d13bbd23d14b25bd00e006757fa7de6d637f4c49e5fdcf4a07f024aea1f53f499e56140df7f6326e0c99cd10d9a7ceac70c4f9343111769b6ac62e1ed", + "digest": "0x407d6005ebd258cd798e326e17786b0b61a927309b8584db513bdb62f4f5ee3f" + }, + { + "name": "random-14", + "domain": { + "version": "25.49.7", + "verifyingContract": "0xb0e0d9999c8c74a0d4ed79414a9f8bf363e9caaa" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bytes[]" + } + ] + }, + "data": { + "param2": true, + "param3": [ + "0x96ae69774e732b9214a3ebb03c0fd01602bc7a5fcd21", + "0x60a6103ace6cc41a8df5b6518b24e6ecd490c13acfc67765f3540a4a7aa93d074a77313622786513f0199d0dad5e012c" + ] + }, + "encoded": "0x8a9a6129ffa166123d1ac6c76c2bfc752f7cf2e64b76b36df081cfc7c032a75b0000000000000000000000000000000000000000000000000000000000000001e8da1f36005f78d7a373d2f0da3b4215c9b2ab40e5a8d62e8ab338374600329f", + "digest": "0x0b1d8e9823e30d163cbd911aea02c15a62bd0bbc0168183ccd2965a8b601a40b" + }, + { + "name": "random-15", + "domain": { + "verifyingContract": "0x6f5c960aebe912340a5a72935aa334afa8fbfe58" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes31" + }, + { + "name": "param4", + "type": "bytes31" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": "0x4a18799bc6b7f0fab7d57bc456346bca7261a53cb04fb48d82dba056", + "param3": "0x8d48a6cc9e0c92080dec2155382a276181f25c746da97f8199f3a846421180", + "param4": "0xb165a49183e897da692ca460c5c88a0597e5e4ad7b43471bac25bfd9a780e0", + "param5": "Moo é🚀M🚀éééé oooMé🚀ooM🚀 o🚀oMMooMé🚀é 🚀oMoé🚀" + }, + "encoded": "0x195b09fb47455d098743f9c930f4078d642ea0a6f994b66198c7213629164dc250d60588d6db4ae7e3b0d4d8f93aed4781b86403d576fb4e374af761f1238cc38d48a6cc9e0c92080dec2155382a276181f25c746da97f8199f3a84642118000b165a49183e897da692ca460c5c88a0597e5e4ad7b43471bac25bfd9a780e000a315cbc15f8ad1d34c761a0523412f8bd958f3b121ab055ad39eed2d1c894c3c", + "digest": "0x859f85bc1d34695b4db0f3650dc448e4f26e1310bbf4386a47154dd0ff2f7134" + }, + { + "name": "random-16", + "domain": { + "version": "46.37.5", + "chainId": 398, + "verifyingContract": "0x7d5c6babf358d15f834e4e66fb38f47029692f45", + "salt": "0xf631d7b0a81f0bb5d43c5c6cbe06f0c46868590f0951afc1b55f38598f5caf4d" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "uint200" + }, + { + "name": "param3", + "type": "uint192" + } + ] + }, + "data": { + "param2": "902991113240896234120897942256968907309321984644966427837857", + "param3": "1793643122398654278545911502385423630752811461294794060392" + }, + "encoded": "0xc905891cccd69edb3dcead4f2229a9b1c0f7ad0264bd9e32ca83cf8d4835ca94000000000000008fdad31cff441c443d69458e4033c11eeb0b4928ce9452c5a100000000000000004926820a408021ed575bd94e89af5672c9c4faaa93adb268", + "digest": "0xa8ca54bd8b0380e9680fee86021be77dd65fe79954ca8aace6708fda1e62d959" + }, + { + "name": "random-17", + "domain": { + "version": "13.22.4", + "salt": "0x9a939ab1fd21216c5fcfed335f5d6ad5e83f7815e6bf7d521dd0341e9445415a" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "string" + } + ] + }, + "data": { + "param2": "0xde2c0dae771d5cb66092b8905ba5691226740d7398459c60712a5793f0c9434c", + "param3": "Moo é🚀 oooéMo é🚀o🚀MM 🚀o MMMoMoooooooo o🚀éoM" + }, + "encoded": "0x686167f4c27dbc607c8b7b3febaeb35fa7dbcccbfac18ae20803b8e2bfc040fb053664f618ae8de97996df7189f0b8b97619489a71e0b0e370e6ef9b581df98208744de9ee650d2089505fa1d121e39ff8bd12472e14e192ad7a450cce4feb3b", + "digest": "0x0b5413c0bce8ba1599a5415a0a8729659df2c4dbfc6f71655c228101a523126b" + }, + { + "name": "random-18", + "domain": { + "chainId": 1154 + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes12" + }, + { + "name": "param3", + "type": "bytes22" + }, + { + "name": "param4", + "type": "string" + }, + { + "name": "param5", + "type": "address" + } + ] + }, + "data": { + "param2": "0x5f7bd6650aedd689f688617f", + "param3": "0x9d8ca86236fa8ca5e654b767c43bc31e4e2be542b128", + "param4": "Moo é🚀MoMoo🚀 🚀MoooM ooMM oMoo🚀 é oooM🚀Mo é 🚀 éo", + "param5": "0xae09d2fea99189d5171ddcd7c90e4ba4902e9df3" + }, + "encoded": "0x7a78c404a07e9f6956aaff71efb4b16130954663e72d5ee2de28e982b75d86675f7bd6650aedd689f688617f00000000000000000000000000000000000000009d8ca86236fa8ca5e654b767c43bc31e4e2be542b128000000000000000000000fb03f67aff6a2b40a0dbb1b99236c9ca92063bb9c1a604b32893a7f03e9364f000000000000000000000000ae09d2fea99189d5171ddcd7c90e4ba4902e9df3", + "digest": "0x680060a5f5fc62a31a89bfa6ee31116827439b3a46de888d9d43b1251fb8a3f2" + }, + { + "name": "random-19", + "domain": { + "chainId": 1013, + "verifyingContract": "0x9b76aa9473e60427cbc99f4161665fc37a013015", + "salt": "0xb99a959f6fcb296e9be34584a14761c7b4ce82e99d4394a5f109ed1c55cde477" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "address" + } + ] + }, + "data": { + "param2": "0x010d8955e5cecc6705b73064baa37a703d65cb97" + }, + "encoded": "0x98edda54668461e736d24a4033f2d11540bceac48ea14c7da0fea73b8b9a55db000000000000000000000000010d8955e5cecc6705b73064baa37a703d65cb97", + "digest": "0x8ca2e0e8b9d5ce1c66d5ea245d6a9c653e10adc303e7440d4298c331b011c503" + }, + { + "name": "random-20", + "domain": { + "chainId": 888 + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bool" + } + ] + }, + "data": { + "param2": "0x981ad5555974b8b6b4f767d774c32f9e09e0009d5d914e29614ec739e70c36aaaa454aab9a9409b890c32e9304c42ec8b05a7f7ac0f60be35f1e", + "param3": true + }, + "encoded": "0x889d1fd6a543c2550a4d6fbf451f7004ee9509e508b7627d82b578e77ed3541a1d8c4d6a1c1c4c8ed69df55267e53b5289aca47b178f775978694815b4f990640000000000000000000000000000000000000000000000000000000000000001", + "digest": "0xc1319be39e82c2e51795b588e89ae2ffa116d8e6e5e0aaff6c9a42379e18e35d" + }, + { + "name": "random-21", + "domain": { + "name": "Moo é🚀éM", + "chainId": 1189, + "verifyingContract": "0x20595d9bc36f43302fc02a5b8b1afcd8751ec829", + "salt": "0x616e7f89169e2cc84d244f9e3fe0e03661dfd04909f43f379752069848cccf7e" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param5", + "type": "bytes" + }, + { + "name": "param6", + "type": "bool" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "bytes[2]" + }, + { + "name": "param4", + "type": "Struct7" + } + ] + }, + "data": { + "param2": [ + "0xb7bdd490b49bd7ab", + "0x864b5bb60e5d3fe67c853222aa05ff96aa441cf26a394fc4" + ], + "param4": { + "param5": "0x109f4bc90e17530b89b8fbbd2c39477a4a8bf23a1109d71902516214aa", + "param6": false + } + }, + "encoded": "0xc870a8ea20ea5a0e48665e1cceac4d0911ebdd5211d9bbe9ea6b02742610630c2274465ff0a09b20e8e027da59fb88f7c11871f7ecd6354e3ed5099296cfd04be1885a775bd5e9fe96ba4a0d693d8c0ff869e2956d2445c820173815e807f2e9", + "digest": "0xfe17ec225aeca7f68177514dcf12e22fb0b39840aa6a6c22c26f59dd033ec5c7" + }, + { + "name": "random-22", + "domain": { + "name": "Moo é🚀M M🚀ééoMoMo o é oMéé🚀", + "chainId": 941, + "salt": "0x504bcce324addceda39d36f209fbfcb3b14f834e21f104979f550ea5c6f9917b" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x7d44e5363b38914b63ccfe012685ce3d2e65121a", + "param3": "0x0e" + }, + "encoded": "0x424c0018d1cc135145554306c5c9e3e9e8a4cca8848cfa101804ff94674c8d6c0000000000000000000000007d44e5363b38914b63ccfe012685ce3d2e65121a7d74985e988688526ac76b8ff8f86df2934c34abd4c430c49bf3b8a821b4e87e", + "digest": "0xb701808badfe14419c62c8108a8123a1531555b8d6c40bd0aea773e4cc7faff5" + }, + { + "name": "random-23", + "domain": { + "name": "Moo é🚀éé oé🚀🚀éoo 🚀o🚀🚀 M🚀éo🚀é🚀 o", + "verifyingContract": "0x4b290dacba7bd6da6bb491d627c27c59abcd55c8" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "bytes27" + }, + { + "name": "param4", + "type": "bytes" + } + ] + }, + "data": { + "param2": "Moo é🚀 éo ooo🚀🚀oMéooo🚀ooo🚀ooo🚀 M🚀 ooMoéooo Méé🚀oéoo", + "param3": "0xb72fa668214dee979e4ab0b212697763c7a644140a47417af60c4b", + "param4": "0x0526eab9" + }, + "encoded": "0x381b9d935686d6436962f0aa124ec705db0c223f0aa58c87e2e87a502e83b175cdd03bb0b8d5f0ab36918e793771d1a727264b826e6d52705aa7d8ac060af095b72fa668214dee979e4ab0b212697763c7a644140a47417af60c4b00000000005315d4abcf9b7169289f8f9fb986abe1e1648425138878b59807cf047bdcf743", + "digest": "0x9d78aed8da7518e44916c6da939b27f32296254456d1d12317f9d8d49414f704" + }, + { + "name": "random-24", + "domain": { + "version": "33.33.10", + "salt": "0xa465767278b9436adbcda02c178d53ced5ad9a5063042056fafac91f3eb256aa" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bytes29" + }, + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": "0xa41a2812f302436d74f6322e3d24f7d0894d445b", + "param3": "0xfbd8fa19905015b516f07997d9ee9ef2a3e70acb6a5cef4d58d25ae9a6", + "param4": "0xf8f1b9b200727a131c0868f5b0d5224e91acdd49", + "param5": "Moo é🚀" + }, + "encoded": "0x3406cf367962412603498937e52eb1fae44b403ffce6931f487e0191dc1da76e000000000000000000000000a41a2812f302436d74f6322e3d24f7d0894d445bfbd8fa19905015b516f07997d9ee9ef2a3e70acb6a5cef4d58d25ae9a6000000000000000000000000000000f8f1b9b200727a131c0868f5b0d5224e91acdd4973afb58374689378893745fc96a2fc65d1568ee4015275cae05c7ad1ba4ee814", + "digest": "0x776fdda1fd58d3c90228f4bfe52e9243a6a0c1b8804f91ecf7570b51038090f4" + }, + { + "name": "random-25", + "domain": { + "chainId": 725, + "salt": "0xc2de9b40a3c72c4b8080784d0abe7e2a81ee8c6d00ade54cbfa186d05b80a30f" + }, + "primaryType": "Struct10", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct10": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "address" + }, + { + "name": "param4", + "type": "bytes" + }, + { + "name": "param5", + "type": "Struct9" + } + ], + "Struct9": [ + { + "name": "param6", + "type": "uint80" + }, + { + "name": "param7", + "type": "bool" + }, + { + "name": "param8", + "type": "bytes17" + } + ] + }, + "data": { + "param2": "0x0e1c5e8d98e793c508605de14b557517086a154a", + "param3": "0x4643f9f0fff83c5992655ea60b4ee4d87962402c", + "param4": "0xe24ad838b2dff3ce1ceb5cf89d5382a3b7ae58e3b83ed04b361dd24e858604e086cf3aae72e10af9157ca91a07aacb76ff5f4e714bf0af4e2767a5c1b7", + "param5": { + "param6": "1037360565969580415751062", + "param7": true, + "param8": "0xb400c0f629151c1c2efc8678b90a90db50" + } + }, + "encoded": "0xda5e84ad82b98296cf11f22beffa9ac554199abd2907793cf612a0cde3a3a6e00000000000000000000000000e1c5e8d98e793c508605de14b557517086a154a0000000000000000000000004643f9f0fff83c5992655ea60b4ee4d87962402cb5c868e1fa67a6af58ad2de258728150a4257a8fc3a0e8b1cd0c693a9154e78a19b8a5510cc83eb41b72cdb218809b5fb097d4f56a210465d7e4434ae4f93ae2", + "digest": "0x20c6d3b7d3a08127d2675417f10192a19404eb7f2b4a7cc826291c200d059c51" + }, + { + "name": "random-26", + "domain": { + "salt": "0x84ecb12e99120d7e16d5ea8b41f3a1712b04779027244978e3c14e6b779bff43" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes15" + } + ] + }, + "data": { + "param2": "0xd9d920215e9cef3f5d2c992b29d02c" + }, + "encoded": "0x3124ca50b2729655ab7183f9cdc9ce21f39c5f9af1539ebbebddafd8d5124eebd9d920215e9cef3f5d2c992b29d02c0000000000000000000000000000000000", + "digest": "0x98647f029b556997bd7cf686927a1075276cdeb949c7324cb258265daa43e9d0" + }, + { + "name": "random-27", + "domain": { + "name": "Moo é🚀Mo🚀o M ééoééoMéMoMooooéoéoo o🚀oM🚀 oMo o🚀 Mo oé", + "verifyingContract": "0xa25337ce36273880f4e9e61f7d6e42cdf375343e" + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param3", + "type": "int88" + }, + { + "name": "param4", + "type": "address" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "Struct5" + }, + { + "name": "param6", + "type": "string" + }, + { + "name": "param7", + "type": "uint144" + }, + { + "name": "param8", + "type": "string" + } + ] + }, + "data": { + "param2": { + "param3": "-127309812032058079971015355", + "param4": "0xfea50d6aa0beb7541421a003b305176bfafd3bf7" + }, + "param6": "Moo é🚀 🚀🚀M🚀Mo", + "param7": "21679346468763708829870107432985082613037936", + "param8": "Moo é🚀🚀M é🚀🚀oMo oo🚀éoooéMo" + }, + "encoded": "0x5ed3e5cf198704fbd48783461bff2bf9894ce18fa02dfd09804f85f9897fe3b6457fa76bc117d82ca5c78822611af029603b99095c728469d2b6e0db0d38430dab622c3246af0064a7ca87eee9696c6f580b5b628a1c3ccc7ca8ccb5d099b5b30000000000000000000000000000f8dddf8de4ce294ba243327c1bb5c1bd7b7017c8ef26c2ec6558fcdaa26969c050886d3cd13aa63fd7c1b4c951a029775a19", + "digest": "0xc01ab63f5b6821f38672244e3f54b38b1f997cfa987996d97c2d0b45e4378116" + }, + { + "name": "random-28", + "domain": { + "name": "Moo é🚀Moéo oéMMéMé o ooo 🚀o o éMo🚀M 🚀oo🚀🚀oM🚀éM🚀🚀ooM ooooé", + "version": "6.36.29", + "verifyingContract": "0xbda80f1b5ee3f31847bfab9e1f2d577a736ae9ae" + }, + "primaryType": "Struct16", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct15": [ + { + "name": "param11", + "type": "bytes26" + }, + { + "name": "param12", + "type": "address" + }, + { + "name": "param13", + "type": "uint240" + }, + { + "name": "param14", + "type": "string" + } + ], + "Struct16": [ + { + "name": "param2", + "type": "Struct7" + }, + { + "name": "param8", + "type": "string" + }, + { + "name": "param9", + "type": "int240" + }, + { + "name": "param10", + "type": "Struct15" + } + ], + "Struct7": [ + { + "name": "param3", + "type": "bytes[1]" + }, + { + "name": "param5", + "type": "bool" + }, + { + "name": "param6", + "type": "bytes21" + } + ] + }, + "data": { + "param10": { + "param11": "0x3c8aa45d6e60df8fa4b94a9f1a9873982cf117b7870019a77257", + "param12": "0x18dbfcc4b58ac047af1fa1ea5014e9a3c122d695", + "param13": "1403160610370024385322518859671151374504293477415157376516004093379141099", + "param14": "Moo é🚀MéM 🚀éoéé🚀 M 🚀🚀 🚀éooMéoMoM é" + }, + "param2": { + "param3": [ + "0xdd89a7e45431dc5bcf2575124ce071addb7e049856e3ec3a698aa73965f2cdebe3d8c1561c943beb06906bc333a5" + ], + "param5": false, + "param6": "0x40cdeaa8cfa786861d28835935341469073906c16c" + }, + "param8": "Moo é🚀o🚀o🚀 oé🚀oMoéo🚀 o", + "param9": "-728201913157045709305151288883895292116444273394221376510603682943551543" + }, + "encoded": "0xdb90bb6421637471a75a3d7bc8dc38f85ab6d86fe66817a5c5e52e1582dc9d8d05eae0968871a1fb36bb967307259c285125d151dee777d1b9bba85ec0c5924ab953967c8b9dd2e0f5cd1fe230ad4ddf4fa6f38f5286db1d29957c90a18c2d8bffff967d7d66a999668fc7fbff14f873fe30522876aee45bc8ad4fbc9c24b7c936513d68064480110d163aeea34e925427d939bc37d8892caa329a9d3558c51e", + "digest": "0x4f9a08cb3212e843a37e628e8a3899c9632ba8fe184f4955aabfd568690c8cbc" + }, + { + "name": "random-29", + "domain": { + "chainId": 356, + "verifyingContract": "0xa2cb255c54cb952b1d29aa906d0db8a0369b07ac", + "salt": "0xa747cdaee63c094c448b58b76e9b7555459bf28fe41e33d8e485334b3955dee3" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "string" + } + ] + }, + "data": { + "param2": "Moo é🚀ééé🚀o M🚀🚀 🚀🚀🚀oM🚀oé🚀🚀oéoM éM🚀éMé o🚀 " + }, + "encoded": "0x5927d86a0ef9a01a131f7a41d2a9c89a8c82e0f454d6b4502f955f90f152eb512a656f0bd407a79f684b714713b1e71478383b1f47d7c72f652658ece534dd0b", + "digest": "0x8f21c436df4d7b8ea1470f3f4cac3d756774982b25a60bd7e76587c6b519df6a" + }, + { + "name": "random-30", + "domain": { + "version": "1.46.13", + "salt": "0x13ae4c3150715b5ad9a1e19f9e5d7acb57041c056751bf3517085406225bc939" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "int136[1]" + } + ] + }, + "data": { + "param2": [ + "8166199623935941567874687986584718264154" + ] + }, + "encoded": "0x4d74029cfac37baeca9753d910ae221b711f6f012a1bea4dab197ee55395b8c7639803471fd3db6691ea1e09d239e931d1e355db6dd3a8e271e91cd893cfb588", + "digest": "0xb6546c223ab20fefa301d938ffbc21f17128f0620fd926a149725887b3cccf4a" + }, + { + "name": "random-31", + "domain": { + "name": "Moo é🚀 o 🚀 🚀M M oooMM ", + "chainId": 908 + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "string" + }, + { + "name": "param5", + "type": "address" + } + ] + }, + "data": { + "param2": "0x4ede0deacb3773e5137435f4d889ed859498566a", + "param3": "0x62dd238d0e2d216ab536acf19569d82284ec73724af965e1e635a5e02de69f89315c86d4b43dd3fea6b5", + "param4": "Moo é🚀éoo🚀MooM🚀Moo oéM🚀🚀ooé🚀 oé oéoM🚀MéoMé🚀Mo🚀oooo🚀🚀ooo🚀 ", + "param5": "0x4e35a3945fb38294c8acf415464978b576dddadd" + }, + "encoded": "0x7f6d973155b0bcc8d11dd8547d4396f95e47a6b1663de76876af0dd85aa48b3f0000000000000000000000004ede0deacb3773e5137435f4d889ed859498566a84c9e1c43faf98cea6c5fcbc1fd1dd44de98d2a6fd8094cd3379479cf19d02d3f60e96d7ac3d6507f6e8030df384f326924853ce6a85f91dfae3efb3d566f6170000000000000000000000004e35a3945fb38294c8acf415464978b576dddadd", + "digest": "0xb6efd1b092fc83b8ad6f1562b7b87e3d06f28ff1ad2287008b557a4b325e4c94" + }, + { + "name": "random-32", + "domain": { + "version": "28.18.35", + "verifyingContract": "0x860a0e50434a1e67fea76e2ecaadd0f7a34606a5", + "salt": "0xa79039bbd2738722f49a7a10b34a89be4701d18545207a60ed7b1a0d647d3ede" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "address" + }, + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "bytes19" + } + ] + }, + "data": { + "param2": "Moo é🚀M oo 🚀Mé 🚀🚀 ooo🚀oMéoéo 🚀🚀oooo 🚀ooé🚀ooo", + "param3": "0x47fe050a8243b24324599b07443a44409ae0ae5f", + "param4": "0x4e9cfb53ea5657c6f71a9f6d180ef603b1491593", + "param5": "0x9bb5cc4641fd491758c28f1334074c4fd8c30d" + }, + "encoded": "0x1cf4f0e08a7941dbcc88554ec00340e272c27c135e2814a9aa84b7a0cb59090ac3fc89c9396771c6833539097c737e43749df63d9374e94038e87806138dbf3e00000000000000000000000047fe050a8243b24324599b07443a44409ae0ae5f0000000000000000000000004e9cfb53ea5657c6f71a9f6d180ef603b14915939bb5cc4641fd491758c28f1334074c4fd8c30d00000000000000000000000000", + "digest": "0x44170d64ef7cf254e72fa3a1fce021939881e52ddc6b53804b7ed17c3cc2cf4b" + }, + { + "name": "random-34", + "domain": { + "name": "Moo é🚀 é 🚀oé🚀o🚀é éoMMo🚀oooéo é MMoo 🚀 é 🚀MM🚀o🚀oo Moo", + "version": "13.20.41", + "chainId": 168, + "verifyingContract": "0x4cb0f9a774003fde250f9498bf59af14a58a4ba6", + "salt": "0xd10a489e053686f001e06c5f95be04abf66384251beee98aac3352a576309497" + }, + "primaryType": "Struct11", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct11": [ + { + "name": "param2", + "type": "Struct7" + }, + { + "name": "param8", + "type": "string" + }, + { + "name": "param9", + "type": "address" + }, + { + "name": "param10", + "type": "bytes" + } + ], + "Struct7": [ + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "bytes30" + }, + { + "name": "param5", + "type": "address" + }, + { + "name": "param6", + "type": "bytes" + } + ] + }, + "data": { + "param10": "0x172fb5da45fc748aab90701f16e488faf3aeb7e2631bdb4e89178e291c54276fc0a09fde49c1d8d83ae459b0de8af4a32e752f7cde484933c819bb984fdd", + "param2": { + "param3": false, + "param4": "0x5f13d3b44f1f7b3e9509e0e6a6e86a82bad560c0463ff6f4107ed0f91ce9", + "param5": "0x854a1ce60d811708da436e758e7bb7cb3c4d3645", + "param6": "0x631b36ea5aac0b4b7a59d000cde1336adc46b54c9e2c27211a" + }, + "param8": "Moo é🚀éoéMo oéo🚀", + "param9": "0xd4116d1167d22db322c0f7ea24958097646ee98c" + }, + "encoded": "0x8d56be8d93acc8d9b7c480a48b942024d438e759597af81d8ce0c269bbfd7ba148f76de9e7e52c7befac76d291947c16f2d706470cb5a7fa41f654e7a6515feab9ae4544a83872d12bd236f00a1e723895219ed2e761b1451b728f7da4c07fea000000000000000000000000d4116d1167d22db322c0f7ea24958097646ee98c57aea085c98b9350d480022e6d063faa8011110987c0cd42488d34ffaad7596f", + "digest": "0xd916f454522d064210bb959fdb97edfc71ed9d6493f69ef3aa59ac602a4cb557" + }, + { + "name": "random-35", + "domain": { + "version": "18.1.21", + "salt": "0xa30efc1f7cb3062cc649929f0661f023168871c712710e3e2bcfb86cea245bfa" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "address[]" + } + ] + }, + "data": { + "param2": "0x6d5b8e2c382bcf3f732b63a56fd3a40216ce312c135083ffd5e345323397d458a568e0b5677f5b037db50782", + "param3": false, + "param4": [] + }, + "encoded": "0x3196893d5e65faa04abf32b95ea06dd0d6c08930740797c9505a8db7c0dd8d783c9347e5b56b01554824ad8ab3894c26f214fefd98de34e7c5ca8fe394ab16040000000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "digest": "0x55d568f5b6d8fcb20a1daf9434f22bef6f84008a548c2011c428c3fefa5f5ecf" + }, + { + "name": "random-36", + "domain": { + "name": "Moo é🚀o🚀MMoM ooé🚀MMM 🚀éooo🚀o🚀oo🚀 oM ", + "chainId": 640, + "verifyingContract": "0xd83848a872fece3b3d46e7db4c2b77d3f860e293" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param3", + "type": "uint208" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "Struct4" + }, + { + "name": "param5", + "type": "bool" + } + ] + }, + "data": { + "param2": { + "param3": "328075064361718410561598645543330760805893258006339352712528380" + }, + "param5": false + }, + "encoded": "0xd9c78b76c5945cdad51cc594f4f98013082d5b29c5acd60ecaae6e197d0282175d5d216ebd03b033f8465a6ad96f1018494e4217e6f613aafe8b727c911047170000000000000000000000000000000000000000000000000000000000000000", + "digest": "0x199e8bfe6ee9ef6a4a030554635b74168da0c20cf8c5a19ec689aa5df1161795" + }, + { + "name": "random-37", + "domain": { + "name": "Moo é🚀🚀 o🚀oéooMMo éMM é", + "version": "28.27.34", + "verifyingContract": "0x7eabc8de425d63e9221ab1d30fa6dd0cefc081a3", + "salt": "0xe0523cb396cb9dc27ff363d713948ac735f273623989b6af7612f2fcd2ff6d2b" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "int200" + }, + { + "name": "param3", + "type": "address" + } + ] + }, + "data": { + "param2": "-444299975383749025331326339923423112873391432830281341721190", + "param3": "0xed41029f84e192af5415531ee38e17f30d120a88" + }, + "encoded": "0xfa093f4ea3bf0aa4213f3f060eac93ca7ab21ae17ace77be8dc0692eb11b3bf8ffffffffffffffb9380bd11977ced6065cd29a646828eb18b6e6f2b19f3c259a000000000000000000000000ed41029f84e192af5415531ee38e17f30d120a88", + "digest": "0x863b7af213ea9f4d6e5bddd79a651e5868a89780ea3fe954aa60bc4265ed20d7" + }, + { + "name": "random-38", + "domain": { + "name": "Moo é🚀o🚀é🚀 oo Mé o", + "chainId": 1268, + "verifyingContract": "0x929fa2120c0710256df5b8617b56ab4e970ecb45" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "address" + } + ] + }, + "data": { + "param2": "0x6271d301aedc2d2eace8d5c39530cb69fa33c087", + "param3": "0xee756a5c2cd1aa40fb2b0ae05eea3e40b7436592", + "param4": "0x7909af95849ea0e6482d4979aa97b6de40184c5a" + }, + "encoded": "0xd76e74eec5c6ba52563c5d6c259dd7ab7b3c1c568662d8e52ee9e9eb1fb3b08f0000000000000000000000006271d301aedc2d2eace8d5c39530cb69fa33c087d37b7d384539b90a02ac9a5fcdffb5ea5e19dcd612cac7a8d08e701244f586f10000000000000000000000007909af95849ea0e6482d4979aa97b6de40184c5a", + "digest": "0x7fa9e8243fd155df5677ac9c26861ade73b0a6ab52e98999956cbef093e96249" + }, + { + "name": "random-39", + "domain": { + "verifyingContract": "0xe3ac435708684db0ae31e22bbefb1e44317338c4", + "salt": "0xe26aafa719c7da18b0ded1aa1520a9366af0fb6b459916877728cb9a5c87a7d6" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "bytes26" + }, + { + "name": "param4", + "type": "bytes32" + } + ] + }, + "data": { + "param2": "Moo é🚀oé 🚀M🚀éMééoo é🚀o éo o🚀 o ééM🚀é🚀ooooMoé oo éo🚀🚀oooo🚀o 🚀oM", + "param3": "0xdc0aa250b183fce60762c98a54246dd7b9bb956bd6341da3e3b8", + "param4": "0xb72dc336b24a1bbf207488efe80ffcb2fcac731fd7663809b3d2fc49ba7dfc41" + }, + "encoded": "0x7dfa18ea85b7f90d6621faeda9cf913de2386da0479309954a0255dc716d1597813bc527d887adf055ba505a819f5c99c5959f37552f3546a3621eecdbab9fa9dc0aa250b183fce60762c98a54246dd7b9bb956bd6341da3e3b8000000000000b72dc336b24a1bbf207488efe80ffcb2fcac731fd7663809b3d2fc49ba7dfc41", + "digest": "0x657847e82a36f749a49a0249eb01d42a8f84e155799a89a361326c7e059f4857" + }, + { + "name": "random-40", + "domain": { + "version": "27.48.40", + "verifyingContract": "0xb01dee94f0bffe39c63b53c94d0a9fcbc1384c7d", + "salt": "0x2d69edf19eed3feff59d5ff3d202299b0a2f7cfd471953c708c84ff2c8ef15e3" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": false, + "param3": "0xaf4961b17878b5ba9013de1d9fd0f3642f1e7294" + }, + "encoded": "0x08b05ab3afcc030e7935ce6c66d5d4b79136f50d1f567b347bde3906d91197e800000000000000000000000000000000000000000000000000000000000000007a9bca0401d98432dd02eb0e29aa6b8a2d7db41d77d60789e3f2a6b4672eb697", + "digest": "0xe8d2de50871488e0d941f58e407218d0e53232673e4f0c087c4ddc60f4b12997" + }, + { + "name": "random-41", + "domain": { + "chainId": 1047, + "verifyingContract": "0x374b2b8301b1edbcc86612a691376d7ac3ced722", + "salt": "0x35b3516e1c75b47e8c6c9e67c454eeb7ee4bdfdce3bff554800152182ef7c097" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "int80" + }, + { + "name": "param4", + "type": "bool[]" + }, + { + "name": "param6", + "type": "bytes4" + } + ] + }, + "data": { + "param2": true, + "param3": "29080156520360861738698", + "param4": [ + true, + false + ], + "param6": "0x5aedc9f9" + }, + "encoded": "0x9ca37edfac674c2ff136c55e6301a602590e506fcacca5c9b6b9620af18ee3d60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000628703dd9fee4a7a6caada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d5aedc9f900000000000000000000000000000000000000000000000000000000", + "digest": "0x6c6d10e7a34cd9b044d3ef2f2ed2d4333e2822ac7d10b38eb6d99bb8b1771bed" + }, + { + "name": "random-42", + "domain": { + "version": "5.35.42", + "verifyingContract": "0x43b33fe40f841899d259fa0c36dea65ec8fde1d3", + "salt": "0x081bea430df1ade6eb0b35829797621ef878f32df1dc4b9d0c53cb94d441390b" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "address[]" + }, + { + "name": "param5", + "type": "address" + }, + { + "name": "param6", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x3b9ca4b5f6b5e21e938265fa8c67e1caf4aab1f01b17be03ae60ee2d6635a495847dedc266f2a7c2e5567b52e52be5d3", + "param3": [ + "0x699d241b2b53540a703d8f00870c1739b6e5f72d" + ], + "param5": "0x0109f2064fb32e6c22911ac905fb319ef0cee5a4", + "param6": "0x0ca1fb3d6077a402783877ceff53" + }, + "encoded": "0x853568bcfdf9ba7ef41211e721fea9318ec93b8bf70306ce21829c25ba577bbd6865c9161273dd536df66549067730a5b9d1f65060fad8a53e1ac0f39ccdaa52f571a282e60d64a3ded8eaa67254087841c598a176a7cd626f00d50732f7f95f0000000000000000000000000109f2064fb32e6c22911ac905fb319ef0cee5a4c435cc0d815f1d138a42be987d6cc47160918ac555121a5bd5278c32fd472060", + "digest": "0x804d08480ce1b1d7ddf3646c58bf0a49a114f62d28e81ec9210e03f4f9f3a617" + }, + { + "name": "random-43", + "domain": { + "version": "24.21.37" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "address" + } + ] + }, + "data": { + "param2": "0xfe1827974ce7e150af244d1b889f747c8f0a776e", + "param3": true, + "param4": "0x13a081fac5b7be3ce686e044bf4da3abef57fe9b" + }, + "encoded": "0xd9df0580bd644a74f3c333bfcc151b8847cff76c671a86edc3130dbf71458cfb000000000000000000000000fe1827974ce7e150af244d1b889f747c8f0a776e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000013a081fac5b7be3ce686e044bf4da3abef57fe9b", + "digest": "0xced726b5f99a87ac8035856b471812b2d20ad43e8e600fe5ef6e82ef52f1d653" + }, + { + "name": "random-44", + "domain": { + "chainId": 437 + }, + "primaryType": "Struct10", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct10": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "int32" + }, + { + "name": "param4", + "type": "Struct9" + } + ], + "Struct9": [ + { + "name": "param5", + "type": "bytes22" + }, + { + "name": "param6", + "type": "string" + }, + { + "name": "param7", + "type": "bytes28" + }, + { + "name": "param8", + "type": "bool" + } + ] + }, + "data": { + "param2": "Moo é🚀Mo o", + "param3": "582504756", + "param4": { + "param5": "0x111983d0af17dcfcc318c61ae1136ee42ccf1f2687e1", + "param6": "Moo é🚀Méoo🚀 oooé 🚀o🚀🚀éMéMooo Moo🚀oMo🚀é 🚀 oo🚀🚀M🚀é🚀Méé", + "param7": "0xd6c6a4a7600a2e4bf9c4add944c09f63cbde8e22b0d6fcbf19615fef", + "param8": false + } + }, + "encoded": "0x52230b1722ba9fa8df5a2874a719206cde8f49cae1cc265121e414b677873a98fb6852300dd5f88a8abd38b78e451c8cb00c5a9868c44b7df99b4a2f1c2d25620000000000000000000000000000000000000000000000000000000022b851341e0d5386101b1d456726a186dea7a1d769e76ac7dcf595f563d047ae9d74727d", + "digest": "0x205d02e271ba4c6b9f25c8f47ee1d77575d64cd4f00e63fffdc59472397d92e1" + }, + { + "name": "random-45", + "domain": { + "version": "47.45.42", + "chainId": 1206, + "verifyingContract": "0xf947022a0e71d11aab373afabfe9befd44681e93" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes29" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "string[]" + } + ] + }, + "data": { + "param2": "0x8bc51a1cd258fe6d63ac29ace059b760205588a0a9161c84c856c159f7", + "param3": "0x413b8e4fe25c1c744f85d99604ca804e2244bd4dab2ce6f5887da8e1d44ff150224b771fa7fcfdd80522c67e2315e1a2", + "param4": [ + "Moo é🚀M 🚀o 🚀o", + "Moo é🚀oo🚀Méoé🚀🚀éé🚀é🚀éoM🚀MoMéMM", + "Moo é🚀" + ] + }, + "encoded": "0x3ae8fde34490f7400f057134dfa1b5e09466c9c820ae931d27906d7f0ad91c9c8bc51a1cd258fe6d63ac29ace059b760205588a0a9161c84c856c159f7000000283f4a8f7f4aa0508213c3acfea1b9eadcc0134f291f7062983fb7b5faa4c0433ce102fe157fdae81a22e96b212ccdb916af0903abd81ed9dede694888ad8069", + "digest": "0x594e4bf0d590269799cca8859ba0a0bbdc1f50f79b62484b426596dd352185eb" + }, + { + "name": "random-46", + "domain": { + "version": "20.6.0", + "chainId": 1182, + "verifyingContract": "0x48828af2bff4cea1847888835dd26ef645440919" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bool" + } + ] + }, + "data": { + "param2": false + }, + "encoded": "0xd827c65b54cb667b8cb0c84a4aa21ffe3d188aa9cdaede527a285c318ad7274e0000000000000000000000000000000000000000000000000000000000000000", + "digest": "0x95645087033defeaf6a222f850ccd5f3f6ff9d051aeb02dd2c25cc7e237f38d9" + }, + { + "name": "random-47", + "domain": { + "name": "Moo é🚀", + "version": "17.27.18" + }, + "primaryType": "Struct19", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ], + "Struct10": [ + { + "name": "param8", + "type": "bool" + }, + { + "name": "param9", + "type": "uint248" + } + ], + "Struct13": [ + { + "name": "param7", + "type": "Struct10" + }, + { + "name": "param11", + "type": "uint8" + }, + { + "name": "param12", + "type": "bytes" + } + ], + "Struct14": [ + { + "name": "param6", + "type": "Struct13" + } + ], + "Struct18": [ + { + "name": "param5", + "type": "Struct14" + }, + { + "name": "param15", + "type": "bool" + }, + { + "name": "param16", + "type": "bytes25" + }, + { + "name": "param17", + "type": "string" + } + ], + "Struct19": [ + { + "name": "param2", + "type": "bytes[2]" + }, + { + "name": "param4", + "type": "Struct18" + } + ] + }, + "data": { + "param2": [ + "0x3cce5e65b51c8ab21c69ab4c6cf7a0098464d6fd4cc4dab8916ac0221f3ee8ea47479755ffbf", + "0xad11241adfe1c3d9ff8487a28064a49b65e77955dd25cbd4a6874161c9c93aa0502f1644dd08ce5b717e08f3eec80232527d509a8da2bcbf" + ], + "param4": { + "param15": false, + "param16": "0xeaba82b14185bf405877677729bd3cf35984e2de6795d26af8", + "param17": "Moo é🚀oM🚀ooééoo é M🚀oéo 🚀 o oooooMMéoéMoMM🚀oMo🚀MoéM é oo ", + "param5": { + "param6": { + "param11": "250", + "param12": "0xdf", + "param7": { + "param8": false, + "param9": "100895587724354576608296576780149850234295977769426801441167174141880048070" + } + } + } + } + }, + "encoded": "0xa2503d8dab2dd52492c8bd1e75e197a963b1be16d8704f24b034c5c3ebb5ae22ab435560740a636c972580194f75d3a1a37686a2281bff1c37e9ca6ccc1c69bebed7f0eb879274b19967141ea60f229549d8509e8c2719506fca12599149d972", + "digest": "0xf87ee3f08c482046207edfd23e1303358eb48bd840500f424192948eed97c044" + }, + { + "name": "random-48", + "domain": { + "name": "Moo é🚀Méoooo🚀 🚀🚀ééMMo o MM 🚀o é o", + "salt": "0xc03f10b7364e134ddc9de679561060f22c44058fc7abab3b8a06eeff8a0cda3e" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x6be8", + "param3": "0x48c2efb8ba7ee5d877ba4641d56d960ef4857d19b913c44af5c4b9bda9cfa25179" + }, + "encoded": "0x39b0d4be9d0cd319e0a49b11a9725cad68c2545bda0a2875a0510a5846e63ce43b716dc9026fa5a0f9d7f44f4f87e3bf20d3ba1c57dc9820987bf547c9cd1c92caefa7da9321f9199f0d71f17e36c56f1ec520e39306893bb0216f64129f029d", + "digest": "0x32e5e620ebdc87817f3c8028e2e1dfa11bc8281ce740d373ec1d3e6944eb795d" + }, + { + "name": "random-49", + "domain": { + "name": "Moo é🚀o", + "chainId": 103, + "salt": "0x3a5a1eb3351d1a1688d37b0d12422c89298146d8fb17ba3c25fb4b5c86c4bac9" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "string" + }, + { + "name": "param4", + "type": "bool" + } + ] + }, + "data": { + "param2": "0x26dfef70c4ef8dcc7b392b64e54778600e4342729ff538043a4180f710d08d7b5456214a42f08ba7fac949be1bbc22b9de57aa01223cb5556b82844077", + "param3": "Moo é🚀o🚀 éMMoo", + "param4": false + }, + "encoded": "0xbb972fe1a70ee0d67e7cacbc55c17b51b6f3a17a25f4f86f5941e8562149d8baf133a0ff1f13504e6c624d2de18b24dcea844936d869bcec139368394b038fd1dd59271cb718f83ded679ab9a17cd95cf12c4045bddd47bb221f8ba9f1d192320000000000000000000000000000000000000000000000000000000000000000", + "digest": "0xf5f4417e3f7452c53925e17a8d761742c795a21d1399bbdbcc6655d28ae01898" + }, + { + "name": "random-50", + "domain": { + "version": "29.42.1", + "chainId": 1327, + "verifyingContract": "0xfa7dc57fcaae354b92e4116c0bdd2cf47d8f689b", + "salt": "0x03da468bb06a9b9dab725571b916aff5422068b4ed5447355b3c5f70bc15171f" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "string" + } + ] + }, + "data": { + "param2": "Moo é🚀ooé MM🚀o🚀éoéé🚀oM éoMMMMoo 🚀 o" + }, + "encoded": "0x5927d86a0ef9a01a131f7a41d2a9c89a8c82e0f454d6b4502f955f90f152eb51cb99a22ed97e79bbd189fcbf151341d2ba13a10693a9f98ff01bde8e4b54b0ed", + "digest": "0xd10b65f29d8c77544a7a31a419b8158854a6efdbd142c11b13e5e914720eab09" + }, + { + "name": "random-51", + "domain": { + "name": "Moo é🚀éMMoéMéMoooo oo🚀 é🚀é ", + "version": "17.12.32", + "chainId": 850, + "verifyingContract": "0xee57c317107b6016ee17355d870066437b91cfc4" + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct8": [ + { + "name": "param4", + "type": "string" + }, + { + "name": "param5", + "type": "bytes2" + }, + { + "name": "param6", + "type": "address[3]" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "uint176" + }, + { + "name": "param3", + "type": "Struct8" + } + ] + }, + "data": { + "param2": "41925907111722419066054857838161787127898051241694288", + "param3": { + "param4": "Moo é🚀M o🚀 oéé éM 🚀M🚀 é 🚀🚀 oo 🚀é o ééMoMé 🚀o o Moé éoMo o🚀 ", + "param5": "0x34cf", + "param6": [ + "0x93ec006c48ba16d99c6a572425637e732a9ea0dc", + "0x31cf2777fa3591e4d92e44b68f531fe304770850", + "0xf193bb64fd886bbb4490a31d7ab87a4e69f72240" + ] + } + }, + "encoded": "0x6b5499a7890f6a8255933b37decd0f637928da8bd61d925b3fc04f155551707200000000000000000000700edea808dc2e1e1937df49f85355a1244560c5d450fb8722e70eec19fe4a54da68f47326495d284ae333f3f2db8057ec987bb743b0", + "digest": "0x95199a1c903ef5b161ea35770728ff9753d9fe4cf63a68001bd910bfd7cd8930" + }, + { + "name": "random-52", + "domain": { + "name": "Moo é🚀éo oéé é M é 🚀🚀oo🚀Mo 🚀oooéMé", + "chainId": 1092, + "salt": "0xab35002bd126820952bb44438b2a342cefd29a7e41533cf101af42d980f231e5" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "int168[3]" + } + ] + }, + "data": { + "param2": [ + "95857240772386493629523551458434344427800456907887", + "28274122495329753421185292621092753236174200542842", + "32557294196900688742163694164485808400870334488946" + ] + }, + "encoded": "0x9c928539a37b7c8e4f1ce136ca12eba2a05b8ae934748884491b03ad7547973a0a839d9c631d1e54947847568fb9b7170b4c91ff638a57cd7bdee89b100734ae", + "digest": "0xf56d12fc86d9c13a69e7e53913981ae56a0bfdc19f6c1693cb3a808aef256f80" + }, + { + "name": "random-53", + "domain": { + "name": "Moo é🚀oooo🚀éoooéoéoé🚀é é Moéo oooMo ooo", + "version": "13.16.19", + "chainId": 568, + "verifyingContract": "0x1c60b5eb2fef17a1cdd14f962e6f7d3b3b6d6500" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "uint72" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "bool" + } + ] + }, + "data": { + "param2": "0x2a82f8de19144e48d8bd0ca7dcdcffc3efdcad1c261eb97bd6111b6918b4daab39158153", + "param3": "1620817067840645147941", + "param4": true, + "param5": true + }, + "encoded": "0x09cfbba2e1e5ea4a3a82d13e5af185c9af63919209274a8b7c749ae5d84b713cb669a821b131bc1c35ea0a46ea180437711dceaf7c7157512bc9794f513ae1c0000000000000000000000000000000000000000000000057dd5af7be83dcad2500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x508f38594346bfeecaf00d106d48313a5fda1a95aad52b5543d5b14b9d7196a7" + }, + { + "name": "random-54", + "domain": { + "name": "Moo é🚀éo é🚀🚀oéMMooéé MéMMéoooooo Mo 🚀o", + "chainId": 903 + }, + "primaryType": "Struct10", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct10": [ + { + "name": "param2", + "type": "bool[1][2][1]" + }, + { + "name": "param6", + "type": "address" + }, + { + "name": "param7", + "type": "Struct9" + } + ], + "Struct9": [ + { + "name": "param8", + "type": "uint216" + } + ] + }, + "data": { + "param2": [ + [ + [ + false + ], + [ + true + ] + ] + ], + "param6": "0x8e95a960e9a83b777c7862a94e8110fe91da147a", + "param7": { + "param8": "86338055400144793659912925038806297757314957088810913205015089413" + } + }, + "encoded": "0xc2160e538078feaa17b54d2e42d2d30202df0ca254993ea38c93773174f229ffc62f64b185683f6d01ccc0e8d936d70806faa97827a9a5f882dfd39e417384780000000000000000000000008e95a960e9a83b777c7862a94e8110fe91da147aafdbe910404b0c3b44c47734e11d0efc9d25900e7fcb2a08b20eb55cf7c271e6", + "digest": "0xbc69ff6a3a430987fe2afffe25c78d68fe98948b160b03aa8bb31dc93bb40cf8" + }, + { + "name": "random-55", + "domain": { + "version": "14.37.24", + "chainId": 406, + "verifyingContract": "0xfa8846e816297a43ce7d94b8c6bdb6cca1159fd7", + "salt": "0x242778aa1964c438a31f0e78cb2939d4452e9498a49b3765a9a401a5ac362230" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes21" + } + ] + }, + "data": { + "param2": "0xa6eacd95abf006c234ec8ada1a0a1efe733fb8fecf" + }, + "encoded": "0xe3f2482dcc01a81435fc0dd8a8d9e82fb6aeac6d724cfcb3ec568286b0182780a6eacd95abf006c234ec8ada1a0a1efe733fb8fecf0000000000000000000000", + "digest": "0x49a860a4b3d28e51559860477bea7a0dd0cd2cc65aefc1be534af93dbda125cd" + }, + { + "name": "random-56", + "domain": { + "chainId": 1035, + "verifyingContract": "0x1c37f1b939feea69ce5757b2ff01a4dbe98cee99" + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct8": [ + { + "name": "param6", + "type": "address" + }, + { + "name": "param7", + "type": "bytes" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "int248" + }, + { + "name": "param3", + "type": "bool[2]" + }, + { + "name": "param5", + "type": "Struct8" + } + ] + }, + "data": { + "param2": "189736845901057709645072716699447242597536589852507924815517840586006295739", + "param3": [ + true, + false + ], + "param5": { + "param6": "0xc84f54254fadc15051904a3aaf01a63695b229c6", + "param7": "0x17e0e79daf5a18eeea785f936e9d0b2f867e5adbf00c319da45f5db04d42397d4b9439754f98bef9ea96a1f6b3d8517c9c272e7d7ba1dc6852c8ea06b9de" + } + }, + "encoded": "0xb9cd0c37eacfb7cce86fa6e1179348a2dffc13cef7976b514a468bdf7afb4063006b6322c21ecaba15e76c656e3fc5d69ed353a0eb9ae49a9c4ef0ed9f0b74bbada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7de75e33b115454660e8bf1399340fd2a08c02c80da600b7f6607e4fdaa98b71dd", + "digest": "0x89a21c0061b072cf4fe51034a22f646423cb79528c45920db9f8dd9b8ef023d1" + }, + { + "name": "random-57", + "domain": { + "name": "Moo é🚀oooooéo🚀MM🚀o", + "verifyingContract": "0xd5fdebacaa6fd0e4c4e3dcb01d49d0d0b5169fd3", + "salt": "0xf46bae2676d80f6d7ed7eebfe927e808a1a9d7f16bb9c5733025eb1c54fb3cd7" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes24" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x11e04fffbb632f04623d274c69004680bbfe47f642d78193", + "param3": "0xc4340156b62bc39a03b5f8bf3405e1" + }, + "encoded": "0x15a4a682c969e6c9e1a691efb9e6eac924562774edc9c70b2dea59192b5ffc4511e04fffbb632f04623d274c69004680bbfe47f642d78193000000000000000059b64b2801ddb0f37604d34c0c2b712b9ba10b111c50bf93ad769dc5372943f4", + "digest": "0xfdd39c246fa31fb5a02b7eed6bc3ccf206bf15199c22155fc730d523c884376f" + }, + { + "name": "random-58", + "domain": { + "chainId": 382, + "salt": "0xedba234675d29838cea84fca64d51c6ec1a8569eb7dc50ab6db9fdf81cbda9c7" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "address[2]" + }, + { + "name": "param6", + "type": "address" + } + ] + }, + "data": { + "param2": "0xea0f9d8e13e45e85a35d02b4523d47aed0e2acb5", + "param3": false, + "param4": [ + "0x0c861e080792c701e98212618cf4fa7fab7bf08b", + "0x899bb3224127617acf0ba2c0002c2f2ab1fa53b8" + ], + "param6": "0xf36ebef74931bfa226e964551dfe43911f2d130e" + }, + "encoded": "0xc143354b22d04023559bed7cae63b574cfb78cfd7ac0c43a128d77d6e5e614ec000000000000000000000000ea0f9d8e13e45e85a35d02b4523d47aed0e2acb50000000000000000000000000000000000000000000000000000000000000000c71de37770f9c52cb0725ff89e17b4cf1847e4d111693996075aacaff8157569000000000000000000000000f36ebef74931bfa226e964551dfe43911f2d130e", + "digest": "0x2d06931eec7d70a1db63d07d25e4b8b90f7bcb3a2b55d972c48278dd66acb0db" + }, + { + "name": "random-59", + "domain": { + "version": "30.30.24", + "verifyingContract": "0x561277eeb6bbd800e12ebc6cd0dbee892d139824", + "salt": "0x14bc6a6ff4765450e40c9f760db83f7b207a736f8588a22106af54f936524eda" + }, + "primaryType": "Struct10", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct10": [ + { + "name": "param2", + "type": "Struct7" + }, + { + "name": "param8", + "type": "bool" + }, + { + "name": "param9", + "type": "bool" + } + ], + "Struct7": [ + { + "name": "param3", + "type": "bytes22[1][3]" + }, + { + "name": "param6", + "type": "string" + } + ] + }, + "data": { + "param2": { + "param3": [ + [ + "0x507f079711e94366216b3db9f773265034311ecd25b8" + ], + [ + "0x5f6c0a03617cd85a8d36eaf3b00f3bf7250d52ef44d1" + ], + [ + "0xaaffa60b2f4aeca0cd5e1633701c0fbc7801574995f3" + ] + ], + "param6": "Moo é🚀oéoMéoé🚀M🚀" + }, + "param8": true, + "param9": false + }, + "encoded": "0xaf138bad46576af052316d07c060c9e4148c2bff6809ec200b5bd3de4aa870cf4f3e0e37be2547e04487ab720f75f451fc5f4feabfe1102ce08d0e4ec14306d000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "digest": "0xaf9d9edf7f72d55542c3a9d8b875cee65261f3aa6c7e96280440c183661bed0d" + }, + { + "name": "random-60", + "domain": { + "chainId": 563, + "verifyingContract": "0x724d9d0a75aeefec930256ab77b13f018432dc13", + "salt": "0xf766cba081e9030cf506f1616682083a65c89daebf5cf7e828d5bf85a47a819f" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "int80" + }, + { + "name": "param3", + "type": "bool" + } + ] + }, + "data": { + "param2": "-149389809661940077828877", + "param3": false + }, + "encoded": "0x773a0a5ad6d608cfce67b33cbffe13f6c510c8e08ce51877432cbe3f5e8efe0effffffffffffffffffffffffffffffffffffffffffffe05d8febbd996b6de4f30000000000000000000000000000000000000000000000000000000000000000", + "digest": "0x638795e70617a8e19fb1971a5531c28225e07cbf26f3330c59f6d5bee2b237ed" + }, + { + "name": "random-61", + "domain": { + "version": "7.6.2" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "uint40" + }, + { + "name": "param4", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x2ea8b4cdab8e0585a626248968a0f3a97dbc1668", + "param3": "113948542974", + "param4": "0xde0c11a1e17e64435e2d0a8414cc368302fe788c8aac8e47741336362229cf9b9c4b029f6b" + }, + "encoded": "0x1bf518570cadc618d41542f220dc4096c36b1bdf93cbd49b2a8d9d8702b1b6540000000000000000000000002ea8b4cdab8e0585a626248968a0f3a97dbc16680000000000000000000000000000000000000000000000000000001a87dcc7fedee76d97debe8dea474b08619fc6a3b04e96d191aa5ddd4309330f5f6cc24603", + "digest": "0xe825e97cef6530ad8cd98b08e3d94b08c18a3ae7be1a742e6c9378b419c266ab" + }, + { + "name": "random-62", + "domain": { + "name": "Moo é🚀ééMMMMM🚀é", + "version": "39.10.1", + "chainId": 955, + "verifyingContract": "0x72c212d52a7da827cf299e1063d0f5481a10aba3", + "salt": "0x911b6be26e46725a5a9b2f66813850cb246cf850f316a8abd17c3255a59b1b73" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "uint120" + }, + { + "name": "param4", + "type": "address" + } + ] + }, + "data": { + "param2": true, + "param3": "267318752341245407126510725002347495", + "param4": "0x12a0cdc5797b0e2cd0fcc3b5f3d63d0b40060713" + }, + "encoded": "0xb1d573600e493816acf7786e0db884238646f98d2925ad6bc1d0e58f7a84557600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000337bd501dc8adfc1e062ad2c26c3e700000000000000000000000012a0cdc5797b0e2cd0fcc3b5f3d63d0b40060713", + "digest": "0xa6448bcf64129f8f3357ad27ea6cb54528261ae82c77fa911cfd42326c5a32b9" + }, + { + "name": "random-63", + "domain": { + "chainId": 52, + "salt": "0x63a0b8d00ebb49dc92aa7466795df26f52f7f097a8951212994dcf084f3115ee" + }, + "primaryType": "Struct11", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct10": [ + { + "name": "param6", + "type": "string[3]" + }, + { + "name": "param8", + "type": "bytes" + }, + { + "name": "param9", + "type": "string" + } + ], + "Struct11": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "uint176" + }, + { + "name": "param4", + "type": "string" + }, + { + "name": "param5", + "type": "Struct10" + } + ] + }, + "data": { + "param2": "0x3e22bfaf4192ea7bbd24be98894f62", + "param3": "8643822919333434052426646511186265705818267649977701", + "param4": "Moo é🚀 MoéM 🚀oo🚀M🚀é🚀ooooéoMoMMé é🚀🚀ééoooo🚀oo🚀ééo🚀 ooé ", + "param5": { + "param6": [ + "Moo é🚀éM MoMoéooé🚀oéo", + "Moo é🚀MMooéoo🚀é🚀🚀é🚀oéoé éo Méooo 🚀M oé🚀oé M o🚀éoé oéoo o", + "Moo é🚀" + ], + "param8": "0x855aef", + "param9": "Moo é🚀" + } + }, + "encoded": "0xac316d647c74bc3589294fae161068a7566854edd7dd16d2eda15b770a4375daa7942ff4d68d8349802c6984bdc9c4c2b6d470e42e79142bbc940d35ac64002400000000000000000000171a57f90c59a9aa6004324b4c1e5ca16b31e5062d65320516b8c2848eb919a422085947b5272cee2812540b5bf353b28c2cb5f048a86ed4f8451f4da89498fab2ccc0b5f4f96071ca26c12b291e2fb6545c1fdf6657", + "digest": "0x3312dae7779358b36e3d0901d23210c35ae47615a6ced82730958afeecba27b4" + }, + { + "name": "random-64", + "domain": { + "version": "12.22.26", + "chainId": 1072, + "verifyingContract": "0xcfadcc6d18290da205685c27be85e3d12daef93a" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "address[]" + }, + { + "name": "param5", + "type": "bytes14" + }, + { + "name": "param6", + "type": "string" + } + ] + }, + "data": { + "param2": true, + "param3": [], + "param5": "0x8e08e58d1d810440dff7199e28d0", + "param6": "Moo é🚀🚀oooéé " + }, + "encoded": "0x1a13a4e4f65db23bb29d9f84dd419677df8345f546cd92242e7e392b4fbc15360000000000000000000000000000000000000000000000000000000000000001c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708e08e58d1d810440dff7199e28d00000000000000000000000000000000000000d7aba156c05cec0dbf187401b9ed4df82bcd9fd30870c0924ad1cf2b4f3d704", + "digest": "0xaf2a42e1f7ec4b6c7b7dba5b36c575bda2972f52479f34190d1c3750e18ad5a7" + }, + { + "name": "random-66", + "domain": { + "chainId": 1336 + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bytes5" + } + ] + }, + "data": { + "param2": true, + "param3": "0xec970b3168" + }, + "encoded": "0x2bc752ac2910b71f3084d69bc9772a7de5341093c84f7c9e5fd2ac361544ad460000000000000000000000000000000000000000000000000000000000000001ec970b3168000000000000000000000000000000000000000000000000000000", + "digest": "0x8feef116af30b282bfe16c1890206276e9aae7dd7f74e5f988614956135e273f" + }, + { + "name": "random-68", + "domain": { + "version": "18.42.3", + "chainId": 5, + "verifyingContract": "0x2909159c78bf78c499a576986e657f6221814a1b", + "salt": "0x4757ed28e3e7f1ce3bdcb44424f8d26cc8f55f00ea55759f5200e5e58c2df0f4" + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "string" + }, + { + "name": "param4", + "type": "bool[3][3][1]" + }, + { + "name": "param8", + "type": "bool" + } + ] + }, + "data": { + "param2": "Moo é🚀 🚀ooMMé", + "param3": "Moo é🚀ééoooéM ooM Mé🚀Mo Mo", + "param4": [ + [ + [ + true, + false, + true + ], + [ + true, + true, + false + ], + [ + false, + true, + false + ] + ] + ], + "param8": false + }, + "encoded": "0xe1a6b9ce8570dfc1929b0986ecaa84c675a38f130aa0dd754f0f3efb28a7946e7b41e0b88acf6e22ccb8ab0ceb0b4e4498e5569bdada5470159cb4aee1977181aec0dcca7af9e7739a3bb043c812bb554c938bd178a9b815ff2bcc12571dedcdcb524ab786db4edc230bef0de43dcb5bc64e388a0e6e7e776ad754bde112e7530000000000000000000000000000000000000000000000000000000000000000", + "digest": "0x93c2c7376679e56c01ad0855a122657ad37474c3c3cf2d943693ed74c9bdf20a" + }, + { + "name": "random-69", + "domain": { + "version": "29.38.34", + "chainId": 479, + "salt": "0x4d41456ce1c41c3d581d10c26cb759d4a47f54ce1a9368f438e2a81977f51d93" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param3", + "type": "address" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "string" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "Struct6" + } + ] + }, + "data": { + "param2": { + "param3": "0x824518b68d26baa46978e389d86ffce76fc865b6", + "param4": true, + "param5": "Moo é🚀éMMéééoo 🚀o🚀o🚀oM oé🚀o oéooé🚀éoéoMéMoo🚀🚀oo🚀" + } + }, + "encoded": "0x30c11efb6065f6bda2985909969cdeae08dca57414e9e0f27cd2aa3b7be28049e16d3c3bef1a3a648aefca75d723e43c4c44ae6a69831e585a5e3cf1af9cb02e", + "digest": "0x5f28a72d46bcf0e734304e0fdcdb6ce0371bff2f2db3c66dbef72582ca768429" + }, + { + "name": "random-70", + "domain": { + "version": "18.40.21", + "verifyingContract": "0xb24a517ffcbfdd9bc47720db3e5190fda2e01002" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes3" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x41ce81", + "param3": "0xc83aff0255120cca20588d23ada5f3f38f7195f030873a49a7d16fe8dcaf2b19ac789fca2b3f90470ffe0345332fdcb0" + }, + "encoded": "0x3ba0a68a11c3149e7b8cce5c07245e59ffa9acdaf38fcc613b25ec0abd0fde9b41ce8100000000000000000000000000000000000000000000000000000000003a478a822fa1170b9116c77ad351ea423f4a9ea13a9942e3f02beff4c8c9e6cf", + "digest": "0x26a000eff8c5171403d5d31329e4675bbb567bf0fb2938737fc72b35070bd0a8" + }, + { + "name": "random-72", + "domain": { + "name": "Moo é🚀é🚀 M🚀 ", + "version": "5.17.26" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes32" + } + ] + }, + "data": { + "param2": "0x1a4984f48e88befe512b3cb96ab6dcd897b12c4178dc46a3eb0174834581a306" + }, + "encoded": "0xf0b1d4f6e88accb50c11c83238640185fa1db3c76ce20f17fa4916dadf9db31c1a4984f48e88befe512b3cb96ab6dcd897b12c4178dc46a3eb0174834581a306", + "digest": "0x56403e65cffb42a3d27fc46982bf5f109216c216e600ae1d5e9eeb0f2d535c4c" + }, + { + "name": "random-73", + "domain": { + "name": "Moo é🚀ooMo🚀oo🚀é ooo M🚀éM oo🚀 éooo🚀 MMoé 🚀oM 🚀 é é 🚀oé🚀ooooéo", + "version": "35.11.14", + "chainId": 1042, + "salt": "0x7b9937e8531f141e3ee6fe381c9a9e86ffdcd0c68a8e1ae17112e620aaab338c" + }, + "primaryType": "Struct12", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct10": [ + { + "name": "param3", + "type": "bytes30" + }, + { + "name": "param4", + "type": "bytes" + }, + { + "name": "param5", + "type": "Struct8" + }, + { + "name": "param9", + "type": "address" + } + ], + "Struct12": [ + { + "name": "param2", + "type": "Struct10" + }, + { + "name": "param11", + "type": "string" + } + ], + "Struct8": [ + { + "name": "param6", + "type": "bool" + }, + { + "name": "param7", + "type": "address" + } + ] + }, + "data": { + "param11": "Moo é🚀oéoéé", + "param2": { + "param3": "0x36edbef26bd4681e7135942feae3864374031194d1426af5a7e481a728d8", + "param4": "0x1a59b3c0be1b6635e52bdf4cfe067940b50d4e696c363000edc866d8d22c9e49398b54f25d4e9718feb3f99eb46ce3751b926fa7855343150f9d", + "param5": { + "param6": false, + "param7": "0xe6e18c2cb91d1abe36baf44ab6122b3fd30a74c0" + }, + "param9": "0xc6013a4ce04bb384ce0b272cd0680e04df0cc7b7" + } + }, + "encoded": "0xeb7ccb02ebd334f8f8df1a4ee2070e684c143ac9a985b10cd81de8a58fc80adbc5dd6b5081adebdb29fdae09d95ee5ea84d03f41c3772434f05e3b05708112fc70204aaa5c94f68894203bf3369b48b4d60e7f149b87d2b0805639a833c2fe66", + "digest": "0x67912c3108d4a59226f95dc0c3c275382f78beac03a86f9e077c1caa1eeec14a" + }, + { + "name": "random-74", + "domain": { + "name": "Moo é🚀é 🚀éo🚀o 🚀o é M🚀é🚀éMo🚀🚀o🚀Mo oMo🚀 oo🚀 éo é", + "salt": "0x370860feeba70f3953279dba52f02a3a04612484aefa84f31663d9e5227e1d6c" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "uint80" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "bytes5" + }, + { + "name": "param5", + "type": "bytes" + } + ] + }, + "data": { + "param2": "908478282363712209846374", + "param3": "0xef8eb40ace87b08ffe0e7aefbe3bd8e6", + "param4": "0x597d2ea26a", + "param5": "0x8922c08275eb23909ccfca4daf11662e5d" + }, + "encoded": "0x76603b49ee0d4f7ea115ee0a57044fe4c0401d1221ad71b9dc5321cc33fef7b900000000000000000000000000000000000000000000c060b4d4a59107f2806606a0b7daf9092ca6ab2e9126f86c784769009fa8f8d71e7e03679ce2ca8d87a0597d2ea26a000000000000000000000000000000000000000000000000000000cd50ee07435f2e2e828292fc6ef0446ca0f9be9bdc428a8eaffa42a5286a965f", + "digest": "0xa75d4290b6749b842bf573b2eb09823bb3873d1027d942b4ea6d4d81b842d6c0" + }, + { + "name": "random-75", + "domain": { + "name": "Moo é🚀🚀🚀MoééMoo M🚀 o MoMéMoo🚀Méééé éééo Mo", + "salt": "0x38eaa8c2cfc07d160da608dbe8f1e194e7effef6978024db13d7dca0f3272c39" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param4", + "type": "address" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "bytes13" + }, + { + "name": "param3", + "type": "Struct5" + }, + { + "name": "param6", + "type": "bool" + } + ] + }, + "data": { + "param2": "0x784f74ad457e1d6fcfb45d7367", + "param3": { + "param4": "0xdce541656a93cfcb9e179045ad051a9ecdd7189b" + }, + "param6": false + }, + "encoded": "0xcb86038251ab323aac49c6b590bcaa00d47d51116aa52134673db28594f5bf75784f74ad457e1d6fcfb45d736700000000000000000000000000000000000000a8a20cb63e84557a5347128e3f0c2a1b5a0afb541230866c1088af198275a6b80000000000000000000000000000000000000000000000000000000000000000", + "digest": "0xefef2081cc8e3873505b925f3297102ae37293e502c1a8f0c8f74ccdbb89d4bc" + }, + { + "name": "random-76", + "domain": { + "version": "36.49.23", + "chainId": 754, + "salt": "0x43db1a3f28a17091824b3c3dab8e15ec297daf2313c6755b3e40e58f96c9b179" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "address" + } + ] + }, + "data": { + "param2": "0x3a0cba0c53b27c471b7897a7d6b055079c47d518" + }, + "encoded": "0x98edda54668461e736d24a4033f2d11540bceac48ea14c7da0fea73b8b9a55db0000000000000000000000003a0cba0c53b27c471b7897a7d6b055079c47d518", + "digest": "0x6e9544e309d43df400883cf848f3963329e1e69e89a787509df5a9d5cefe94c7" + }, + { + "name": "random-78", + "domain": { + "name": "Moo é🚀 ", + "chainId": 1205, + "salt": "0x9af868b51e603e4c79a4f3ec3f3117dc294b46a36297214095a50f193489bb42" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "bytes15" + } + ] + }, + "data": { + "param2": false, + "param3": false, + "param4": "0x60217b1a8953bfec781042b8770a75" + }, + "encoded": "0x1676a9ea413a00e543593a76cb92d87b3f3d82e3116ed0efa051c85413c5ee3d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060217b1a8953bfec781042b8770a750000000000000000000000000000000000", + "digest": "0x7f79e4826551d80cda20954308c0daf2e009e2af2aa6f3d60bec8130d535dda6" + }, + { + "name": "random-79", + "domain": { + "version": "6.7.22", + "chainId": 483, + "verifyingContract": "0x55f4aa781b99afe9ce65b85e20b467cbdec997e6" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct7": [ + { + "name": "param5", + "type": "uint80" + }, + { + "name": "param6", + "type": "bytes18" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "bytes8" + }, + { + "name": "param3", + "type": "string" + }, + { + "name": "param4", + "type": "Struct7" + } + ] + }, + "data": { + "param2": "0x8b52a6ddb851805f", + "param3": "Moo é🚀🚀🚀ooo🚀MoM o🚀🚀é", + "param4": { + "param5": "610461354364077444926076", + "param6": "0x7161dd90da510a700714562a8e29d7bf559f" + } + }, + "encoded": "0xfcabf7393dcfae718d48a70508ca009b50740ada3608bceaff6b492ed20c200f8b52a6ddb851805f000000000000000000000000000000000000000000000000aca36f7ecb9904e737ae9a06d9a7bc75f52075619eb5d2238d49e56ff0722a4c50896c94a314c8d9e77fdb0734871b909b734cdaac41d6f6412bac6bbe685e74", + "digest": "0x52bc2e8e33e9a8f5c1e02b4eb1af26d9bfb646f90a802b87e7b05e1c492334b5" + }, + { + "name": "random-80", + "domain": { + "name": "Moo é🚀 oo é ", + "salt": "0x12196565c18218e3d5c30fb8c3ed8aa5368b9270d1e50f96dae8c01c9524bd66" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "uint152" + } + ] + }, + "data": { + "param2": "0x51f4089446d4fac6b978ebc92cb8c136a3ec12d4", + "param3": "0x9fa41910ccf9", + "param4": "1327849360637990991145689530428201101848957792" + }, + "encoded": "0xc3cf69c88a7f7d51e14da0539c7562c4aef44fdccccf126abab02153850a06c900000000000000000000000051f4089446d4fac6b978ebc92cb8c136a3ec12d43550fb9376fce556153ac9c01b5a3d92905e20a0f5e9d20c7f84b82b55b23996000000000000000000000000003b8af68e30d0b55cd77e2a766ab742aacb5360", + "digest": "0xfa4436f23aab9a7adce0a1ed9ccb76fb12aa9c3fd4ea8f550d3d9c21ea8ad71b" + }, + { + "name": "random-81", + "domain": { + "version": "37.42.30", + "verifyingContract": "0x8ddfee525b882a427923e62ea4c6c4f15fd30ac4", + "salt": "0xea7e38d5a4a991401101f92da453029636a589cc8a5a04f5e8b821d09fb72d62" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes6" + } + ] + }, + "data": { + "param2": "0xa15ee47cd2ae" + }, + "encoded": "0xb6ad09a6e56a9b085d21c37fc35456a42e929d83a6c454464108bba8e5bd24eaa15ee47cd2ae0000000000000000000000000000000000000000000000000000", + "digest": "0x5cf352f0b86d7a40b2722d6fee422cc31791ea6a756e975f94cc418482322967" + }, + { + "name": "random-82", + "domain": { + "chainId": 1294, + "verifyingContract": "0xedd346d21be942f85ef9d7e2837019da832bdd15" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "uint216" + } + ] + }, + "data": { + "param2": "Moo é🚀o éMo🚀oM", + "param3": "60842439233483756494403810394413324880914448649588060989930178516" + }, + "encoded": "0x0005f47efff5a6a0a15e05a2eec2b6e6fc783b60032aa8390118dbd32ba2cad636c6269b518467469df2499c64aa468f9cb44ac0c27f5aff6efe92d99caae298000000000093e657c796b03e22877711b903453f372f0a33b18b1f15119187d4", + "digest": "0xd4949695b7d6eec2e8c8f26d6d861ba735fcd61670fbca8de68609e0fd469e30" + }, + { + "name": "random-83", + "domain": { + "verifyingContract": "0x7b9546d050c94a8270fa5c0d0e37ad2df4a1e763" + }, + "primaryType": "Struct11", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct10": [ + { + "name": "param5", + "type": "bytes" + }, + { + "name": "param6", + "type": "bool" + }, + { + "name": "param7", + "type": "bytes27[3]" + }, + { + "name": "param9", + "type": "uint176" + } + ], + "Struct11": [ + { + "name": "param2", + "type": "int232" + }, + { + "name": "param3", + "type": "Struct10[1]" + } + ] + }, + "data": { + "param2": "753575330828539899242077719223027729803561407233093589597780073631396", + "param3": [ + { + "param5": "0x43e53fca9177478563526d0765abe7705b1808451964d8207fb75278cac13fb991bb4dff4c6dde00456d5236a93fd20edc2081b46c087d9f", + "param6": true, + "param7": [ + "0xa413dea0bd7fb350af2baf9e1878c127d2ab62367c57b6d4b4efc8", + "0x7514110a681f7d3bf5b932d467bedbdeee6681d6cb7a454978d6b2", + "0xdb56718cbc96a605ae9624a29a2432db87f2ff1cc1f86e2e70648a" + ], + "param9": "57122701991999599773377300580648345488081114848136112" + } + ] + }, + "encoded": "0x7c13f5ac1c582fab4bda02838e5b34f88377ed3a9f2e39c4e9a99259893244cd0000001bf3a027ad30dc440fff233a7cc1bb6d49fee7c5273eff291e2f99cea417512f0ab3c462fc44f916934f29d7ab18f18c1b7cffe28b41d46b729680442e", + "digest": "0x2d36f076787c1920a351171a2c32575d984b68f652b1dca4db83687b2be45551" + }, + { + "name": "random-84", + "domain": { + "version": "0.4.17", + "chainId": 911, + "salt": "0x3e7b8591b2ff12889933bff797d082b473fc6519049106aa59b07753e926bd66" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bool" + } + ] + }, + "data": { + "param2": "0x41ca2691711b6289b07e9d60adcd530d82049e195a22202170b18328a7852d66398d41a006185887266fa7aad4ac89bfb33f94dc6cd2eaa7f2b9b12a01", + "param3": true + }, + "encoded": "0x889d1fd6a543c2550a4d6fbf451f7004ee9509e508b7627d82b578e77ed3541a549ef74b3d255ff952161e092604766989b5f79184cb72d5f1687d04ddedb4390000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x789a03f8f59d24aee8073b378663b9289f823791b818602a0477434b99c8b768" + }, + { + "name": "random-85", + "domain": { + "name": "Moo é🚀oM o MMoéMé🚀MéMéM", + "chainId": 900 + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "string[3][3]" + } + ] + }, + "data": { + "param2": [ + [ + "Moo é🚀MMo 🚀🚀MM oéoooéé", + "Moo é🚀 éo🚀 🚀oéoMo", + "Moo é🚀oééoéM oMé Moéoo oo M MMoééoooo🚀M🚀o🚀oéMo oo é Moo ooo oo🚀 " + ], + [ + "Moo é🚀o🚀ooéMMooooMo oo o🚀 M🚀Mooo oé🚀o🚀oéoM 🚀M oéo🚀 🚀🚀 🚀o🚀 M", + "Moo é🚀oéé🚀ooéo ooooM🚀🚀éo🚀🚀🚀ooé🚀 éooM🚀oooooMoo Mo🚀ooooMM 🚀 🚀", + "Moo é🚀oo🚀M o🚀oo🚀éoMoooM oM M🚀ooMM🚀 éo MooMM éooo" + ], + [ + "Moo é🚀MMMééo oM o🚀 🚀🚀 Mo o🚀éo🚀oMoé éé oo🚀éé🚀Méoé🚀🚀oéoo 🚀", + "Moo é🚀 🚀M", + "Moo é🚀oo🚀Mo🚀🚀oMo🚀M🚀 o MMoo ééMoé MoMoMMooééoo🚀 éo" + ] + ] + }, + "encoded": "0x988b57712611b9efb362d55270a70ca3e280c7c23ee803db000637ee03249611aa5a4b824d61608ae0c2f6d5840f3f4e9f9984b3536adf111a3b3f81e01b75c0", + "digest": "0x42bfc8f80f73b02a800f2cf5f3b9b96c6774a43c706758c8f34f1fabf946b001" + }, + { + "name": "random-86", + "domain": { + "name": "Moo é🚀Mééo🚀oé", + "verifyingContract": "0xa55e763720cf41f5a539aab57701a95d60e29f67" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "uint104" + }, + { + "name": "param3", + "type": "string" + } + ] + }, + "data": { + "param2": "1292496995405503073422960358486", + "param3": "Moo é🚀MM o🚀o🚀 éMMoooéoo éé🚀oé🚀 éMoo🚀é🚀M é🚀oo Mo🚀 éoo" + }, + "encoded": "0xa7b111f9ba803946689ccd05331e3dfd450deaf9afc546b5d2a08764dbb3075f0000000000000000000000000000000000000010504874d57b4ef8afc891f456a48ff30b0c7e041b00beb25671621131298873a003e9ec839b5d75eb5b1da286", + "digest": "0xf3af9321483c3d61bcdda3a128184aa6841318dc718edc3be9a2f0b976416641" + }, + { + "name": "random-87", + "domain": { + "name": "Moo é🚀 éooo🚀Moo🚀oooMMo🚀🚀o ooMé éo o🚀éM ", + "version": "45.45.47", + "chainId": 759, + "verifyingContract": "0xdd7404edd91ced2e440ae26be5de770826936aa1", + "salt": "0x3e9fe589ec829de82a24cfdfb4f51be7b494d92d767ddce47df39f2d695fef40" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes31" + } + ] + }, + "data": { + "param2": "0x76418c1f3cc8305025ce913e271c62064302cfc52a3cbcee02ffae444e402b" + }, + "encoded": "0x5d03dd39f516dbdce0dda1249a18778b381083c568572fa40e677a1e8bcba69176418c1f3cc8305025ce913e271c62064302cfc52a3cbcee02ffae444e402b00", + "digest": "0x70669d88e5b14dde860f7967400d4001ea51ad347d9dc8e9e14a78a046620a0f" + }, + { + "name": "random-88", + "domain": { + "version": "34.19.0" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bool[3]" + }, + { + "name": "param4", + "type": "string" + }, + { + "name": "param5", + "type": "bool" + } + ] + }, + "data": { + "param2": [ + true, + false, + true + ], + "param4": "Moo é🚀o éo🚀é Moo🚀Mo🚀 éoMoooooM ", + "param5": true + }, + "encoded": "0xeb561f00a2ce847d36d192a18b66be2e5938b7c84798b9a1730ef44ce41ef7c35c6090c0461491a2941743bda5c3658bf1ea53bbd3edcde54e16205e18b457922e1277d90577b137ca94be5c47d97fdd62924edbcd364fffd8f2543a0b3974cb0000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x284ff781d137b80a6aedaf25217692a7bee1529b50f717d20fc8b113ea3d10eb" + }, + { + "name": "random-89", + "domain": { + "name": "Moo é🚀MooMé 🚀é é éM ooo🚀M 🚀oo🚀 🚀oooo🚀éooooM 🚀🚀 oMé", + "verifyingContract": "0x94104688cc800c04a9f4ce356606469f7aaf0889", + "salt": "0xccd084925ccd16ac0a852763036118c175fe5a86811c7ed8ba75bd427a63985b" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "address" + } + ] + }, + "data": { + "param2": "0x7af6a9843bfac96994bcecebe57b40d67942fded" + }, + "encoded": "0x98edda54668461e736d24a4033f2d11540bceac48ea14c7da0fea73b8b9a55db0000000000000000000000007af6a9843bfac96994bcecebe57b40d67942fded", + "digest": "0x7db9f61f14ad00540fd7f51c7adeeff792ab7ef3bdfd672713223f0ff3920fea" + }, + { + "name": "random-90", + "domain": { + "verifyingContract": "0x9511e9dcad6fbe5e6693a1d7031a592f27c5c4ef" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bytes16" + }, + { + "name": "param3", + "type": "uint56" + }, + { + "name": "param4", + "type": "bytes25" + } + ] + }, + "data": { + "param2": "0x88f0dd9c8cbee263cf947a650a3b3151", + "param3": "17583036303696475", + "param4": "0x00153b38e3509586ea81d62acfaf69f58033c03989a5e9ed83" + }, + "encoded": "0x192ce62b78aff9164de71a0394d492eb37f524dfda52e333ccd477c065fbe73a88f0dd9c8cbee263cf947a650a3b315100000000000000000000000000000000000000000000000000000000000000000000000000000000003e77ada8f4625b00153b38e3509586ea81d62acfaf69f58033c03989a5e9ed8300000000000000", + "digest": "0x39c13ee9471e159919485ab461d454a50ca52a6ddd8cdadfbed90326801f74ee" + }, + { + "name": "random-91", + "domain": { + "version": "48.32.32", + "verifyingContract": "0xdc2f8681bcb020c14bb5a61803be1f1904934a7c" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bool" + } + ] + }, + "data": { + "param2": true + }, + "encoded": "0xd827c65b54cb667b8cb0c84a4aa21ffe3d188aa9cdaede527a285c318ad7274e0000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x465f1b1db471abcc586e028f388b54cb4e0c9d341d9c03fd4def6118ca7ac479" + }, + { + "name": "random-92", + "domain": { + "name": "Moo é🚀🚀MMéo 🚀🚀MoooooéMM🚀ooMoo🚀ooo 🚀o oéoo 🚀éoooé🚀Moo 🚀éooM🚀é🚀", + "version": "15.24.22", + "salt": "0xf6b0ebe21875667066601b50ad91163654013e109e51fae6a8bf19a988a51adf" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param3", + "type": "uint160" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "Struct4" + }, + { + "name": "param5", + "type": "bytes25" + }, + { + "name": "param6", + "type": "bool" + }, + { + "name": "param7", + "type": "bool" + } + ] + }, + "data": { + "param2": { + "param3": "990067310911447424079721892655020403107523900579" + }, + "param5": "0x929ecef7eecff36ca4a793303bfeb2f7666d3015f472177f92", + "param6": false, + "param7": true + }, + "encoded": "0xfc75a8485d94b0cf924739d8db8392a3933b768aaf87990e0ef313c9613af2d569d3dc7ee6ddfd3cff85001b724976fea388b0d40fe7864b4d79e32eb76adc8c929ecef7eecff36ca4a793303bfeb2f7666d3015f472177f920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x650fa8632ebb3ad17d74fd519317c5bd99cf2210d6742be16bba20ad7bdb3055" + }, + { + "name": "random-93", + "domain": { + "name": "Moo é🚀MéMM éooéoMoo🚀 M🚀M🚀o🚀🚀🚀🚀oo🚀🚀🚀Mo🚀🚀🚀M o🚀oMMoé M M" + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + } + ], + "Struct8": [ + { + "name": "param4", + "type": "bytes21" + }, + { + "name": "param5", + "type": "bool" + }, + { + "name": "param6", + "type": "bool" + }, + { + "name": "param7", + "type": "address" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "Struct8[]" + } + ] + }, + "data": { + "param2": [] + }, + "encoded": "0xef6a7dac2342e48bc7bee2421009cf3129bbeb0bb7fdeaba99402bea15f82c76c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "digest": "0xba75038176156de4c9a80a8bb70ac20bb140c22b707179be3ae4a554a4e8ea23" + }, + { + "name": "random-94", + "domain": { + "name": "Moo é🚀 🚀éooéoooo ooMo éMo o M🚀Mé🚀ooM o Mé🚀éoMMoo", + "chainId": 1017 + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bool" + } + ] + }, + "data": { + "param2": true + }, + "encoded": "0xd827c65b54cb667b8cb0c84a4aa21ffe3d188aa9cdaede527a285c318ad7274e0000000000000000000000000000000000000000000000000000000000000001", + "digest": "0x69ec47b02da2c0ebfa801692ca474f282d9f0df84f87c45cdc921ce1a0d860bb" + }, + { + "name": "random-95", + "domain": { + "version": "18.32.12", + "chainId": 742, + "verifyingContract": "0xabe3c4f5cf4ed1b97303bd7cae8b067c5e7f8c26" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes[]" + } + ] + }, + "data": { + "param2": [ + "0x38a9ee766abe7a928c112125e65ffb984ace", + "0x3a3613418bc9b1045fe5809d" + ] + }, + "encoded": "0xfbb1adeb7d907dcad24d9dcc6c70efeb95e9983697f2b3d761bbc66df10b6de0c645b2e2e519bae0fadbaf7ef2932226f7e7935d3d837af12839bd360aa64a4d", + "digest": "0xc58c6e7c7e79b525438c151e97c6457f8c4c7b3065827d36e227d6efdbd5cb94" + }, + { + "name": "random-96", + "domain": { + "chainId": 239, + "verifyingContract": "0x0f77912b8136385729a659bd3ef9107a61df2481" + }, + "primaryType": "Struct36", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct12": [ + { + "name": "param11", + "type": "bool" + } + ], + "Struct25": [ + { + "name": "param21", + "type": "bytes" + }, + { + "name": "param22", + "type": "string" + }, + { + "name": "param23", + "type": "uint232" + }, + { + "name": "param24", + "type": "int104" + } + ], + "Struct29": [ + { + "name": "param20", + "type": "Struct25" + }, + { + "name": "param26", + "type": "bool" + }, + { + "name": "param27", + "type": "string" + }, + { + "name": "param28", + "type": "string" + } + ], + "Struct30": [ + { + "name": "param19", + "type": "Struct29" + } + ], + "Struct31": [ + { + "name": "param15", + "type": "address" + }, + { + "name": "param16", + "type": "bytes" + }, + { + "name": "param17", + "type": "bytes" + }, + { + "name": "param18", + "type": "Struct30" + } + ], + "Struct33": [ + { + "name": "param10", + "type": "Struct12" + }, + { + "name": "param13", + "type": "string" + }, + { + "name": "param14", + "type": "Struct31" + }, + { + "name": "param32", + "type": "bool" + } + ], + "Struct36": [ + { + "name": "param2", + "type": "Struct8" + }, + { + "name": "param9", + "type": "Struct33" + }, + { + "name": "param34", + "type": "string" + }, + { + "name": "param35", + "type": "bytes" + } + ], + "Struct6": [ + { + "name": "param5", + "type": "bytes" + } + ], + "Struct8": [ + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "Struct6" + }, + { + "name": "param7", + "type": "address" + } + ] + }, + "data": { + "param2": { + "param3": false, + "param4": { + "param5": "0xa997ae99319d4d5f78001116304b85963cfd598ae95fcc739b489ed254c80862bcefb6dd5c83fed172b8" + }, + "param7": "0x6a437c4aa417145b8550cb480a73690dc14b69c7" + }, + "param34": "Moo é🚀🚀Mééé o 🚀 é 🚀éo MMMo Méoéo", + "param35": "0xed7ea3d3b80622c23d53b27611234455c18fde3d2ed4b55c99a0d1afaa6b15dc9f", + "param9": { + "param10": { + "param11": true + }, + "param13": "Moo é🚀M ooMooé Moo🚀éMo🚀éoé🚀🚀🚀é🚀 Mo🚀 MMo", + "param14": { + "param15": "0xba4bc495f2ea2017b703f7ef1fcbbb762fd05bae", + "param16": "0xceb6a00304eb1d36e62a93652e03722fa1978be1a5b799a6715055006e3de8d49f47f5dea681b7c3f3e032351f494f4eebd5ecfc2ea1", + "param17": "0x53ceecbbeef73e6004a2a48e4b38e8c524fd820f8ac5feba048a31d2c1244c4be8f824f1146f5d882aac2ac4d0421443b56141d09e9b9fc1256c469446", + "param18": { + "param19": { + "param20": { + "param21": "0x575b70fdb462625a1e9cdbee09c61a7a9704ee2a1cbdeba468344e2f97f548158c56b0", + "param22": "Moo é🚀ééM éé éoooMMooM ", + "param23": "3630081370417832362319236809711268993163922661583325307782224246317793", + "param24": "7856537978551137247557348592909" + }, + "param26": false, + "param27": "Moo é🚀🚀 ooMooo éo oM 🚀oéMM🚀oMMooéoéoMoo 🚀éMooéooo MM🚀 oo éo🚀oo ", + "param28": "Moo é🚀oMMéoM o" + } + } + }, + "param32": true + } + }, + "encoded": "0xf9e484b4d24731dcead8e64be7ead35857e953e16e64f5a50ed612f8605ce07d78b6a6b52e423f732676bd55ebd747cc95b670636328d911128444f847b62abd043e6379a56f021f2d7de4165f4f085e23e25ef8e536f8c2415663bfc2ef9323655ae94c06fc9d476b0d105722d4a32d1eb7a4b5529891ec029139fae945d061fcafb084efc157e2ff1daf20bdd536dd513ed329787f2f85f3c3e2c52b597d3b", + "digest": "0xbc43bb6f933954e8ed291b32d35556398a692421734dab354bb9401c2ecaa775" + }, + { + "name": "random-97", + "domain": { + "verifyingContract": "0xc0b2427daf81b3b1ae287b45177cd8cb2dd7fcf0" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "string" + } + ] + }, + "data": { + "param2": "0xa145dd9dccf1d0d72382ec1f2d82d7cd48827ec3", + "param3": "Moo é🚀🚀éoM ooooéo Méé M o🚀oééééMoMoéo🚀oo🚀 Mo🚀oo🚀oo o" + }, + "encoded": "0x666400a396b19434e5bdf93d49163a67dd8b6e60e8df8160e510c7c1288ac5da000000000000000000000000a145dd9dccf1d0d72382ec1f2d82d7cd48827ec3d6991f578c45fb43694bc4e1cf51abc5fb10782beff88449580449e1ab8b1b09", + "digest": "0xce67b3dc8f8249f8ee121de29a726e1c1f4ac4b73971002fb69823d3e752b5b0" + }, + { + "name": "random-98", + "domain": { + "verifyingContract": "0xd2489de35e4726e26c6d21423d8627a34ed723b1", + "salt": "0xdee197f170390ffe117985bc1b6f75d2aa76cffd744a1ed741d9e5fdef371804" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bytes2" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "bytes8" + } + ] + }, + "data": { + "param2": true, + "param3": "0x2512", + "param4": false, + "param5": "0x0f8158ca29114619" + }, + "encoded": "0x23b6f6f83199a6201a90b8b8b9457c300d054549f0d8c6084fc8a0b44442f7f30000000000000000000000000000000000000000000000000000000000000001251200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f8158ca29114619000000000000000000000000000000000000000000000000", + "digest": "0xe4baa2c2a442cd32eaabe94c6db4c30460bd5ab3e50e1238cd265e7e39a5b17f" + }, + { + "name": "random-99", + "domain": { + "name": "Moo é🚀 o ooéM🚀🚀🚀éé🚀éoé 🚀🚀oéM éMooooM ooooéo M oMMMoo🚀éooooo ", + "version": "44.14.34", + "chainId": 401 + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "bytes26" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "string" + } + ] + }, + "data": { + "param2": "0x77c8ed30964f4ad426b83e5a079c394eeb6108670d59ea82bbef", + "param3": false, + "param4": "Moo é🚀 o oM🚀 éoMoé🚀MMooMM🚀 oo🚀🚀oo ooMoo🚀M🚀M" + }, + "encoded": "0x22ff007229938669cf96193b9dcf351dadbe0c48990093a41d72b39335e9accb77c8ed30964f4ad426b83e5a079c394eeb6108670d59ea82bbef000000000000000000000000000000000000000000000000000000000000000000000000000037ed224a35fef81262bbee1f953d29657ee71ff814272f38dd451a46d46ab71f", + "digest": "0xdedd776daec0f194b00d73d63004c5e0883fad5072a458f61ba77635fe04b766" + }, + { + "name": "random-100", + "domain": { + "name": "Moo é🚀M éMooo 🚀éM M 🚀oooMéo🚀MoM🚀o🚀oo🚀oéoM🚀🚀éo🚀o é 🚀🚀 MéMooéo", + "version": "47.45.45", + "chainId": 1297, + "salt": "0x46fd6ce92f74a7398373a2ccbcb0585fe3453b45e4a6a0a03dcab2c2dc9c9d7f" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "address" + }, + { + "name": "param6", + "type": "string" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "bytes21" + }, + { + "name": "param3", + "type": "Struct7" + } + ] + }, + "data": { + "param2": "0x48cd5f1c09c5e268f1a924b1aa9d6483e7de7344da", + "param3": { + "param4": "0xee40a1c631d8f9a0ed7522896b5af8909914caa6", + "param5": "0xf4e494cef1caac185b2886e37a0c0df00b8ccc95", + "param6": "Moo é🚀🚀éoMMoMoéooMo o M🚀o" + } + }, + "encoded": "0x8efe36edac72ec5f57c5c2283101ce2d7121dad612fdb566b4b332088a533f1048cd5f1c09c5e268f1a924b1aa9d6483e7de7344da0000000000000000000000490aa4d83fa47e2e7ec10d335cc7598977c6a4c02ac383ac4f0498c6fcf0370d", + "digest": "0xc757c9b58178cdd87b024fc62b56cde9056291433a95211420bfc2fd3dc67804" + }, + { + "name": "random-101", + "domain": { + "name": "Moo é🚀🚀 🚀éMo M ooMoo🚀 ooooo🚀Mo🚀é", + "version": "32.48.49", + "chainId": 1182, + "salt": "0x89cb0d39315e605914b2629ef0e737a9b2a18c3393c649515dcad65464619c68" + }, + "primaryType": "Struct18", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct13": [ + { + "name": "param10", + "type": "address" + }, + { + "name": "param11", + "type": "bool" + }, + { + "name": "param12", + "type": "address" + } + ], + "Struct16": [ + { + "name": "param15", + "type": "address" + } + ], + "Struct17": [ + { + "name": "param4", + "type": "Struct8" + }, + { + "name": "param9", + "type": "Struct13" + }, + { + "name": "param14", + "type": "Struct16" + } + ], + "Struct18": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "Struct17" + } + ], + "Struct8": [ + { + "name": "param5", + "type": "bytes" + }, + { + "name": "param6", + "type": "bytes" + }, + { + "name": "param7", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x6dcdf91a71234de95982294b661b0be4040ab340", + "param3": { + "param14": { + "param15": "0x6e821dcdcc749da3ccacd453a49ba1484ca8cc05" + }, + "param4": { + "param5": "0x8f32b8d15469bb5a8cddeb0167cd84302a4e426eb67e11405ab05aac13b295828323e287c95df22a50869d5dd7ce", + "param6": "0x5456f8009eb577a667fec8439a686e117fc007519326c10d2e9e55d870266cc277694e42aed00e176912b316d8a91ad20009e8abd316d63963ed4f749c8c9e", + "param7": "0x561026b99073b6eecdf3c4c6d47c27e2754a923f461b79c523362b936a" + }, + "param9": { + "param10": "0xe59adaff5dc1857e78e568e4a1d128d73b117e42", + "param11": true, + "param12": "0x4eef176f86a9782d9191463852afd6dd3a1abae3" + } + } + }, + "encoded": "0x3542196ee308e13b334816ef2496b2d489531edbfedf1df81b61e1d68142a6b30000000000000000000000006dcdf91a71234de95982294b661b0be4040ab340d6736ac6f05a75e17728b8ba7bdb28a31b515912dada4600176132be7e17f85f", + "digest": "0x06dadcc084886d4e4d42c01748794cc70125d59dfc9140a304ac4eecc93faaa5" + }, + { + "name": "random-102", + "domain": { + "version": "5.37.45", + "chainId": 1112, + "verifyingContract": "0xad34d80f19994d30f98da4a9127394233f5d1b62" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct5": [ + { + "name": "param4", + "type": "bytes" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes29" + }, + { + "name": "param3", + "type": "Struct5" + } + ] + }, + "data": { + "param2": "0xa22678edf23dbbd8eaff7e09c5a6898c086e15f5b9afa1d3085ef7c551", + "param3": { + "param4": "0x3d04e4139a6340cf4e183cd5ee6b6d0f585ebad98bbe98a6934a4880a940095e66da08286166fe86feec2b680597deeb4486089095d235" + } + }, + "encoded": "0xa8831e2b1ae12bad49bd738de2fec417a85c70cbd1582c58b1a0fa67d0db417ba22678edf23dbbd8eaff7e09c5a6898c086e15f5b9afa1d3085ef7c5510000004e3b46155fd76195aa056c321070eaf751287eb0839bf1f1f03f0b67d98a5331", + "digest": "0x53b91d82e450b29ebfcd9d912233db26fd277b4ea288c15a4700981b56a723da" + }, + { + "name": "random-103", + "domain": { + "name": "Moo é🚀o M🚀 MoooMéM🚀🚀oé 🚀o🚀M🚀o éMo ", + "version": "34.7.4", + "verifyingContract": "0xffb9dcc2ad72de5d51a6523c3c59db76b5efce82", + "salt": "0x91a6bbeac26f0d774f89f90732838632f7848fba09dccbbbfc4dd0d0fc1a21ae" + }, + "primaryType": "Struct5", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param2", + "type": "uint168" + }, + { + "name": "param3", + "type": "bytes7" + }, + { + "name": "param4", + "type": "string" + } + ] + }, + "data": { + "param2": "52618101586894465619352011808458733029823328733625", + "param3": "0xed40337a19d528", + "param4": "Moo é🚀oé🚀🚀éoo MM ooéééM MMoM éo MoooM 🚀oo🚀oooM🚀éoM oéMéo🚀" + }, + "encoded": "0x166448b3a08b4d0577e607bbf8fa9117e476d4eebfef40d0a03af3022fc95d3c00000000000000000000002400b54743f81e79d07dbe7589e7130815622ec9b9ed40337a19d52800000000000000000000000000000000000000000000000000fcce90f9868722c814b5068c652b2374b1623dcf15ef57b3a67abfb337c9b30d", + "digest": "0xde37ba3588f474a46a8f87b3a97d06f80c18f5f640c2c82eee6b8d35009a2710" + }, + { + "name": "random-104", + "domain": { + "salt": "0x1eda86bf849f89bc2e6f69245118892e38bc6e78ae6b8952228a26f52872db44" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": "Moo é🚀ooo oo🚀oMoooo🚀M🚀M🚀oMoM🚀 M oooéMM🚀o ooéé", + "param3": "0x734299d683c01075c7d7806cabbf" + }, + "encoded": "0x4d0024736263d208aca6e84c7bb7336060a12a4693f70ea14290ed4308d052e586c6628e3abdd5327542024ebfd60ba121feeb94ad0a9fc69718ad35d60e8d7dacc5b4662798e9bfefc01e39285d731e00c77445dad6f1ce9bb875db4cd56e11", + "digest": "0x25bfcd9f9bf4070fa8e64500fc1f03d8b47e1d8475454f4164f235b568b61373" + }, + { + "name": "random-105", + "domain": { + "name": "Moo é🚀ooéoM 🚀🚀 o🚀ééé é🚀éoMo", + "chainId": 1004, + "salt": "0x4bf151c92fcec680b466e8f725517067ecba2bfebd218159b4f7865020861285" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "int40[3]" + }, + { + "name": "param5", + "type": "int40" + } + ] + }, + "data": { + "param2": "Moo é🚀 o 🚀oM🚀M 🚀🚀éooM🚀🚀éMoéo", + "param3": [ + "242858918476", + "77291718371", + "530770037136" + ], + "param5": "263215721237" + }, + "encoded": "0x47b2e0706327e941b7095dbab4500c0798ada3576db783a0499106e8538863be00db7a448333a0944bbe0ded5bee79fc3ea07f15863bc059c42eefdc8a3db436175773b0cff47dcc6167eafef357b7743e0fe0c2e5912473777f63bd463b41fa0000000000000000000000000000000000000000000000000000003d48e12b15", + "digest": "0x9ff750f7890c19f215900f6fe0a413c0a18a8765e974c8d73b996f78ad62c0f9" + }, + { + "name": "random-106", + "domain": { + "verifyingContract": "0xfceb71a9ad2869c8e3dff6fa3669abc9352f783d" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "string" + } + ] + }, + "data": { + "param2": "Moo é🚀 oMooMoéMoooMo🚀éoMooM🚀M🚀oM M éMéoé🚀MoM oMM 🚀o🚀o🚀o" + }, + "encoded": "0x5927d86a0ef9a01a131f7a41d2a9c89a8c82e0f454d6b4502f955f90f152eb519053df716c21aad94a049e52bc52aad715c95913062abd88cd324bdc0e09d147", + "digest": "0xbee1559cffdba5659309d50ed1ad306c33a388b34a1535fd5404851db7fa4ab3" + }, + { + "name": "random-107", + "domain": { + "salt": "0x5bfb5f78bd6682c97b6f3c94bc4cf62d34110e5ad83b21b3f9432fbeaf8bcd4f" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "bool" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": "0x26d3edf93ed79e6435ed818c07a5dd71b20c7690c3c09850f10f3155ff7e2c1b7e6d993cd4f2df0e05488c19ea16e55e14da0596492eadcd1ae2", + "param3": true, + "param4": false, + "param5": "Moo é🚀🚀éM 🚀🚀Mo é Méé o M🚀é" + }, + "encoded": "0x89e191a0c9d59f32cab1f2423029c95a85ca34531f959e94053e40ebf4267c5f4fccd6381664502c41c49bc5cd078cffe187640d7f9304c0661bb223f9b2dcdb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fd174bfd259833e8efb11ee94ba88bfd1632028092b0028084e3ce4c0015cd34", + "digest": "0xdc19c7f5a4fb303efd1e2de89b9ca2082a6d702dc248e95764d90a109cd986ef" + }, + { + "name": "random-108", + "domain": { + "version": "39.28.36", + "chainId": 631, + "verifyingContract": "0x9bd5ff86e47b56b27505902cc94b3d6329a1ed9f" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct6": [ + { + "name": "param5", + "type": "address" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "string" + }, + { + "name": "param4", + "type": "Struct6" + }, + { + "name": "param7", + "type": "address" + } + ] + }, + "data": { + "param2": "Moo é🚀o🚀 éooooM oo🚀o o", + "param3": "Moo é🚀 Mo", + "param4": { + "param5": "0xce4186253cc508af322c4e39cff34a1319599a15" + }, + "param7": "0xd75f12aef677e43bdaa89783ee4572178e3bf2a7" + }, + "encoded": "0x0cf85620ea91e290d99f71f9ee10e2d73daa1b4b71b823e2362954720b7005706d7c4cf22de5351fbb6d76b5fa30da35546a802285ffee4d2bbbbbb9b6363631f03d6b228022926635e1c91913f4f990e5091fdfb5833fa5926f70aef635fd07cbed95fc50b5e3a119bc2286b468bb71a1d3fda6d9b488e82b6f9d38eae3f1fd000000000000000000000000d75f12aef677e43bdaa89783ee4572178e3bf2a7", + "digest": "0xde95998c10032e5774f76f2cadc5e385237bb061d35ca1ff3e3fec1abc60b2c5" + }, + { + "name": "random-109", + "domain": { + "name": "Moo é🚀 🚀M🚀éooé oMoé", + "version": "47.13.9", + "chainId": 1135, + "verifyingContract": "0xf3e8de92425a724a4b5f5f34ff462f4a21c022a6", + "salt": "0x92a39b51b11fe26a4b7c9b5c9dc46e4eed900408b0acdaade7ef2d2000f2180c" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param3", + "type": "bool" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "Struct4" + }, + { + "name": "param5", + "type": "bool" + }, + { + "name": "param6", + "type": "bytes" + } + ] + }, + "data": { + "param2": { + "param3": false + }, + "param5": true, + "param6": "0x2b9eb331163da92c413824164a25f6f94e6e101867847a81de73eb550e5587bcf8737d49f18648d069dbeb0a88bd48c4806a0bd22d07fe7ee7f03096ae61f1" + }, + "encoded": "0x92bcc5ebbe1a24ca641c980aeedbf345d2bb96c75c6e7160a63416ce671e5ba350ba05c95cd64746bc1afc3818f62a6d56861e27a783ff9f39b0f6dc1bebd746000000000000000000000000000000000000000000000000000000000000000114e055471446e3c12424b16ad746b49bb92201f598be3c5f5c500e39cd4b420c", + "digest": "0x26ed036a8e9356433ec6273d9d6bc87f49faacb9b4aee0c1922ab2054032a5dd" + }, + { + "name": "random-110", + "domain": { + "version": "33.16.36", + "salt": "0x685eeb5072a1173bec4979c7dfdc054601f6f80cbe7ad78f4eb43a7e1bfbf55d" + }, + "primaryType": "Struct7", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct7": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "string[1]" + }, + { + "name": "param5", + "type": "bytes32" + }, + { + "name": "param6", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0xa413fc1c6885bc0c48bf8084ef2521d68ee45bc1e23b79e72a7e414511", + "param3": [ + "Moo é🚀🚀ooo🚀Mé🚀M 🚀é🚀é🚀éé M🚀oé🚀ooé🚀Méoé🚀Mo M MMMo🚀 " + ], + "param5": "0xa1f41b79c9af58bec8b31385ecf4c6f1418a351add6fabfeabfa2014583520e4", + "param6": "0xff444eb48a465c6021e011bafad0310066ac09abe890fbe1159732d8f010ca0474270fb7a911db0dfb09882fbb87c29df1f1bf87" + }, + "encoded": "0x2e43045a9a14c67d9b0a9014b72f4aa002f40464467aed0285d4c0c05453173c13b6f03fd29a02d0b024351ffe30c322d189714f11a5645864b1d1ae509c2e6cfe3999130ddf7df630cb54ae95658105ce7dd2c1e39561092b26d42f71c0089fa1f41b79c9af58bec8b31385ecf4c6f1418a351add6fabfeabfa2014583520e436b28fe9e0f31ab8023143ce0634d9618d6068007d0eb02006adbb5fce6c648c", + "digest": "0x853e9a5edaa2da1980831dadec0754c352e34785ecf55789d599a00e28287f70" + }, + { + "name": "random-111", + "domain": { + "verifyingContract": "0x96733f3f5e8bcff66190bf82dc5523bbc8145456" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "bytes4" + } + ] + }, + "data": { + "param2": "0x1ba2e5ab" + }, + "encoded": "0x19a687863ba581a953b0f694f34073f5005a5d39e5c94be277688507ea013a261ba2e5ab00000000000000000000000000000000000000000000000000000000", + "digest": "0x7f0d4714c742f29a9f2a182af25643153529da444383e342937489226f5a0a15" + }, + { + "name": "random-112", + "domain": { + "version": "44.26.33", + "salt": "0x2287f7611aabf794bc8f829715f8794eb76fc9c73ba6143df65e32b231cc8e55" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes30" + }, + { + "name": "param3", + "type": "int152" + }, + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "bytes27" + } + ] + }, + "data": { + "param2": "0xab54e61a59de9271cf657d72cc1fed2256d52d003f3ca02ad8e407182637", + "param3": "-316082391023394535331711337027447687645790587", + "param4": "0x0af88ce740fb6aa140d5e7a7828bfb6755fd7f98", + "param5": "0xd0ae690c13a9cefd7fdf00cc425174f32afc2c13f94bf6fcb96c87" + }, + "encoded": "0x821c71dc6eceb8c412faf525df599ffeb9b576bb83836862f7c6d2bf3817f7aeab54e61a59de9271cf657d72cc1fed2256d52d003f3ca02ad8e4071826370000fffffffffffffffffffffffffff1d38d565f73f2bb8b6566354cf4080bf37e850000000000000000000000000af88ce740fb6aa140d5e7a7828bfb6755fd7f98d0ae690c13a9cefd7fdf00cc425174f32afc2c13f94bf6fcb96c870000000000", + "digest": "0x2bea9c81bb7324309e6659333720bcd45837c9360578495badf83b04d2c602c7" + }, + { + "name": "random-113", + "domain": { + "version": "40.24.13", + "verifyingContract": "0xc246f6e3450948c0f556d212e3129013f3bbdf3f", + "salt": "0x0c5313fdf2e387a82d3e2ce3eda9de53e5c65bfea57db445206b3a4532fc9d10" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "string" + }, + { + "name": "param3", + "type": "int200" + }, + { + "name": "param4", + "type": "bool" + }, + { + "name": "param5", + "type": "bool" + } + ] + }, + "data": { + "param2": "Moo é🚀éé 🚀 🚀 🚀🚀é", + "param3": "-58887618035548045232392023063198065294192444334212910225231", + "param4": false, + "param5": true + }, + "encoded": "0xa161771f2f5479ff0f53bcfbb589145f09ab64fa5e603ddd44010178ec5e3f62d5e9200f0ca4e5342abc1609bb3d7f8a1d820568d292e810a5b38eff5cf8c2f8fffffffffffffff69e6094a73803f15dc86478bdaeca4e2c460355eaee2ee8b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "digest": "0xca0aeafff982a7caa90778ef79c02370f41d7d3c118d6f0674db47aa844dcb53" + }, + { + "name": "random-114", + "domain": { + "salt": "0x53dd66e28993d92f3726c54eebc889ee1feb5de9e6956f17916a70af94a9be8c" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "bytes23[2]" + }, + { + "name": "param4", + "type": "bytes" + }, + { + "name": "param5", + "type": "string" + } + ] + }, + "data": { + "param2": [ + "0xe5efc795069c358388b3f891b191fae431455542adeab9", + "0x270b5f56338f2e2f812a703007e9b0efd6b563e140f758" + ], + "param4": "0x6339392fbd707f0e31c2d9069e3903c19b7d37766ae856d49d18d3d9012d313ac1803f91d08af3fd5d7534f11c6f29476ef6c7302d9f5cdb7e408ab9", + "param5": "Moo é🚀🚀M🚀éo🚀 oé oéé " + }, + "encoded": "0xcbe088c466df5bc47ff7eb50eee07ae89b3ad92aa609d8de035f94d7e942142df1274645ab982ea41af65c3e80ee1ef7d1c848bcd352be42d34068c3d48695726d07a447e03c51b86b9c89ffe0fe4fb894f1082820e4a6ca78b0a32fa2d3ac3cffd3f56909e6332406c11c8e04dd583a0302d9e70ba15e08c78ebc314a6f3542", + "digest": "0xa6298b22e1312894d0867b42c22acac11b272a64e8826554eb644f019ced7080" + }, + { + "name": "random-115", + "domain": { + "name": "Moo é🚀éM éoo🚀🚀🚀MMMM🚀", + "chainId": 519, + "verifyingContract": "0xb6a9e28479e2eefe2b652cd1035e244aa631ae8b", + "salt": "0x37afd12343de89e1a0d00825845be1fff4e39ee71c0047c70e39802a5c647e1c" + }, + "primaryType": "Struct8", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct5": [ + { + "name": "param4", + "type": "string" + } + ], + "Struct8": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "Struct5" + }, + { + "name": "param6", + "type": "int64" + }, + { + "name": "param7", + "type": "bytes" + } + ] + }, + "data": { + "param2": "0x1a23dd5b36e844d8ff6f162b51fe79f412ab64ecfc0a08f0701ab744dc0a", + "param3": { + "param4": "Moo é🚀o🚀é🚀🚀 🚀 oéMo" + }, + "param6": "-7428993099217415080", + "param7": "0xebcf5f2e21ef4078d79de76bc2136de32d78b8da45785d9320293cf88f56fdbb7ed2d99971bdc91313" + }, + "encoded": "0xf9efb6691f7dd1e64ca5c079b4a65046ce7e9b124f0b5a82fca4df1cef20cbf7fe19a4668dfcc60d76d18f9fdb5404410f46b99cd9c46102434bcfe4b002810aa039e88b3516312fbf1a2f8ba092aadc17e7aba94dec383eac1c3f9d30cd41cfffffffffffffffffffffffffffffffffffffffffffffffff98e6ea23025154585e3ed849708604724bc345250b999c8afbbdc5d2d7d899f6b7f0306fd22804c5", + "digest": "0x4c0c04f6ce70c4bbb681ef0ad6b6398acb8b7c6ed135e03749d01ac7581e6aaf" + }, + { + "name": "random-116", + "domain": { + "name": "Moo é🚀🚀🚀🚀M 🚀o🚀Mo🚀MMM o o ooo M🚀", + "version": "36.49.20", + "salt": "0x153291d7e60f50493d9bef0386f2e52efa990e8ef60f067395b548a323336f52" + }, + "primaryType": "Struct17", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct11": [ + { + "name": "param9", + "type": "bool" + }, + { + "name": "param10", + "type": "int104" + } + ], + "Struct12": [ + { + "name": "param8", + "type": "Struct11" + } + ], + "Struct14": [ + { + "name": "param6", + "type": "bytes12" + }, + { + "name": "param7", + "type": "Struct12" + }, + { + "name": "param13", + "type": "bytes27" + } + ], + "Struct15": [ + { + "name": "param3", + "type": "bytes" + }, + { + "name": "param4", + "type": "bytes21" + }, + { + "name": "param5", + "type": "Struct14" + } + ], + "Struct17": [ + { + "name": "param2", + "type": "Struct15" + }, + { + "name": "param16", + "type": "bytes" + } + ] + }, + "data": { + "param16": "0xce845349870b816ffa1153a0d0d74a4fd43a536acba89d7800946365a8185361b43757a6c74d0bc23c99281b20fa1f21efc8f9e70260", + "param2": { + "param3": "0x9be214b7b1e40a654367ce51d46d42eefa6aa7583582ad890407c9a7db193b4a23423edabd2ca74f7bff562e7666b14ff056f859623d", + "param4": "0x70b9c3d3590df445cd2a809ff3fd39d14633ed606d", + "param5": { + "param13": "0x945110dc2331d4d36e6625c582a213f159fd3785e81a1ac51adfa4", + "param6": "0xb74aa08d1da2d00b53573848", + "param7": { + "param8": { + "param10": "7382596839099108206672673364998", + "param9": false + } + } + } + } + }, + "encoded": "0x2404a0d0da38cc2a26c0cae1fd80a615dcead8277266a934eb557d4a2a7b7616058530b4284971e4882f70ed579c18add8c7bf057fab40370e1641f4a2c1e84f26bed6a2942cc3da8e01ab975174dc95d1634c469b28a05029e7a338f26447a5", + "digest": "0x2859aeba18c02d3b96c7cac2c37cb1fc02efeb93bc0162e93cf849f24fc48ec0" + }, + { + "name": "random-117", + "domain": { + "chainId": 404, + "salt": "0xca3833452e02a6b4fa1ac8abc4b15c96f2d7646e05ac0dc999df4c02381fdb4a" + }, + "primaryType": "Struct3", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct3": [ + { + "name": "param2", + "type": "address" + } + ] + }, + "data": { + "param2": "0xe298d05b8a6eee625460e7ffde7a4080b66181e2" + }, + "encoded": "0x98edda54668461e736d24a4033f2d11540bceac48ea14c7da0fea73b8b9a55db000000000000000000000000e298d05b8a6eee625460e7ffde7a4080b66181e2", + "digest": "0x0e9b9a6735b599e2aa2bd15b5a6b6e35ba3f28a6a7727883d8f7b63a9bb6dfc6" + }, + { + "name": "random-118", + "domain": { + "version": "29.19.11", + "chainId": 1069 + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bytes19" + }, + { + "name": "param3", + "type": "uint112" + } + ] + }, + "data": { + "param2": "0xa187410677f35e34d7d2d4a67323f45587a17a", + "param3": "2374623193016793084186176676934718" + }, + "encoded": "0x6d5a7844c94095e64fa9ad1a945731964eeecfab4dafa5aa7d52244c21f7fabba187410677f35e34d7d2d4a67323f45587a17a000000000000000000000000000000000000000000000000000000000000007513f55b61db9e82c36d9b97b43e", + "digest": "0x40254d9a8b1827c010a5df5a2e776142c72a8cb6ac9dca1e4e56853db63c637b" + }, + { + "name": "random-119", + "domain": { + "name": "Moo é🚀MéoM🚀Moé🚀éoM é ooMéMé🚀oéMMoM🚀éMo o 🚀 éé oéé🚀o M🚀o ", + "version": "23.47.23", + "chainId": 392 + }, + "primaryType": "Struct14", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct10": [ + { + "name": "param7", + "type": "bytes14[]" + }, + { + "name": "param9", + "type": "string" + } + ], + "Struct12": [ + { + "name": "param4", + "type": "bytes" + }, + { + "name": "param5", + "type": "int200" + }, + { + "name": "param6", + "type": "Struct10" + }, + { + "name": "param11", + "type": "string" + } + ], + "Struct13": [ + { + "name": "param3", + "type": "Struct12" + } + ], + "Struct14": [ + { + "name": "param2", + "type": "Struct13" + } + ] + }, + "data": { + "param2": { + "param3": { + "param11": "Moo é🚀é ", + "param4": "0x087123d5b3662f", + "param5": "731211289069049313617748368694424686603157878585440644275800", + "param6": { + "param7": [ + "0xfec28eba8cdd8454e8a263553157" + ], + "param9": "Moo é🚀éo🚀MM M 🚀🚀o MM🚀o🚀éo éé🚀 oé🚀o Mooéo oooMo " + } + } + } + }, + "encoded": "0x66a8655159b0710afca0f457c3bde2322122bdb9a1fea4237e6c302a129fa9c76a011fb94ca2e8ba68ca2390abc1167bab6b644ce5915ec5f1165b3ce7572375", + "digest": "0xbb821d9f1b55a93033ab1e22aff08ea2cdbae58acb7799b89ac7f9583020c16c" + }, + { + "name": "random-120", + "domain": { + "name": "Moo é🚀é🚀é ooM oMo Mo🚀🚀ooé M🚀🚀MooMo Mé 🚀oé oo o🚀é", + "version": "2.8.22", + "verifyingContract": "0xd92defa9762b6708d9306f94e639013de8bd2b4e", + "salt": "0xf2b1503c65653a66bb23b43d0b646d9920e2968aea19375f3f744ab0e2d5d3df" + }, + "primaryType": "Struct6", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct6": [ + { + "name": "param2", + "type": "string[2][1]" + }, + { + "name": "param5", + "type": "bool" + } + ] + }, + "data": { + "param2": [ + [ + "Moo é🚀ééoo🚀🚀 oo🚀éo oé🚀oMM🚀o Mooééé", + "Moo é🚀🚀ooééoM🚀" + ] + ], + "param5": false + }, + "encoded": "0x73e644b97783bf4c80cd97dff29c383f1205915fd9399b0a95ccc9d335d190d6e3d0ef52ef1875273cf8cadc1df7b0c681dc2c124e44110285e59de2514e06680000000000000000000000000000000000000000000000000000000000000000", + "digest": "0x9d331f60c2e243c0c380f493df01d216381cbdfd1e8726bf2d95623b966e12d4" + }, + { + "name": "random-122", + "domain": { + "name": "Moo é🚀🚀Mo éééoééé oéMMM oM 🚀o 🚀MoMooéoMéé oo Méé éM", + "version": "38.16.6", + "chainId": 1155 + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct8": [ + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "string" + }, + { + "name": "param6", + "type": "address" + }, + { + "name": "param7", + "type": "bytes18" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "Struct8" + } + ] + }, + "data": { + "param2": "0x1a97d3dd8afe04195e4cf65f6642bb9abf0e30d0", + "param3": { + "param4": "0x5438b331d76c3e973291921307c08d5137bccb2f", + "param5": "Moo é🚀oooo 🚀oo🚀 oo éo🚀oééé🚀o oo🚀é🚀o Mo🚀éo🚀éoMéMMM🚀 MM 🚀é MM", + "param6": "0xa2c5910463111798e60a5dcea5d09fa3928dd865", + "param7": "0x38aeb5bff041e7eb1186d63e6dc85a5972fa" + } + }, + "encoded": "0x4dc6c24fe5adc7b222933880278854e343fff0c6e3008ff0ae0acb2676515b800000000000000000000000001a97d3dd8afe04195e4cf65f6642bb9abf0e30d0031afafd11b84538ee39d9de32f0581663dde8f1b5b8413f1693cadaf1f5f383", + "digest": "0xcf807730a8b53a7c355704e7acd17208573fe6f07eba715f9c3eff5552130cd7" + }, + { + "name": "random-123", + "domain": { + "name": "Moo é🚀🚀🚀oé o🚀 MM🚀 éoé🚀 🚀ooéé 🚀éo🚀 é oM🚀Moéooo MéoéoMo", + "verifyingContract": "0x6fb9e64197fbfffeb79e710b1786fad0adcded2a", + "salt": "0x50e5121d17089bc449b8a20c541511a7fdd92d31a6e6f028fccd96044f12e2eb" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "address" + } + ] + }, + "data": { + "param2": true, + "param3": "0xd1f004a769a4d83c51ef78ae86c9f45497820157" + }, + "encoded": "0x210ade7f30d7f00dbd3bcfd9b6e33d421cb4677f314bb1d18b47c7532f4a33da0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d1f004a769a4d83c51ef78ae86c9f45497820157", + "digest": "0x3607930da601b81fc487c79b4c2a6a5fd546a2ff2f80e5e45693813adf27a56d" + }, + { + "name": "random-124", + "domain": { + "name": "Moo é🚀 🚀ooo éoéooMM oo🚀Mé🚀o🚀🚀ooo MoooM 🚀ééo🚀é éMéé o", + "chainId": 737, + "verifyingContract": "0xa67338c83e7cad895cd912fd10b293c30b93507c", + "salt": "0x29fec8e11edc8a14fed2ebc136bb9718842edaa9fa0661f05b23adba9bbd360c" + }, + "primaryType": "Struct11", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Struct10": [ + { + "name": "param8", + "type": "address" + }, + { + "name": "param9", + "type": "string" + } + ], + "Struct11": [ + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "Struct6" + }, + { + "name": "param7", + "type": "Struct10" + } + ], + "Struct6": [ + { + "name": "param4", + "type": "address" + }, + { + "name": "param5", + "type": "address" + } + ] + }, + "data": { + "param2": "0x289a7fc0abbf5814916b435aedd05110f990b8a8", + "param3": { + "param4": "0xc91643ad99f82f44075c7b2c3176d9fd070b7854", + "param5": "0xa45759a377d7c8f1e6684c1ff727b0b33e812797" + }, + "param7": { + "param8": "0xfb13444aafca282020cc4a4c5fa66eeee5c9a215", + "param9": "Moo é🚀éoo🚀 éM🚀oo o é🚀MoMooM MoM o🚀éo🚀 Méo🚀éoo🚀 é oMé o" + } + }, + "encoded": "0xe41195b80dea8f516fb631cf6457d52b859a33fee20b1678715321d816e04f34000000000000000000000000289a7fc0abbf5814916b435aedd05110f990b8a8c975b7d342e5f9bd4cece3275d900bc4463445fe2c102fc24cdd8bdd9c741af46d6c322f4335555294c4862917e57478c76ba1b8b90655a5134f7532df97e50d", + "digest": "0x8d1983077b551e2dc3ff4d7c564c4eaf4d8ac90e5d66ff1f778bc642dc729582" + }, + { + "name": "random-125", + "domain": { + "name": "Moo é🚀MMooMo Moé", + "version": "49.24.49", + "verifyingContract": "0xcf398d52a18e0a6f91a16c23bae18afd490e004a" + }, + "primaryType": "Struct4", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Struct4": [ + { + "name": "param2", + "type": "bool" + }, + { + "name": "param3", + "type": "bytes" + } + ] + }, + "data": { + "param2": false, + "param3": "0x40caa66524b856" + }, + "encoded": "0x08b05ab3afcc030e7935ce6c66d5d4b79136f50d1f567b347bde3906d91197e80000000000000000000000000000000000000000000000000000000000000000f234b4abf550f95ad2b3e18a8327dfad72bafbc9c735d4d70db98855f86e4d3e", + "digest": "0x8869dd15921fcbfb0942af0803bc4a69e79254d54aecffd8d092de03241b7b29" + }, + { + "name": "random-126", + "domain": { + "chainId": 1089 + }, + "primaryType": "Struct9", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + } + ], + "Struct9": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "uint152[1][2]" + }, + { + "name": "param6", + "type": "string" + }, + { + "name": "param7", + "type": "address[1]" + } + ] + }, + "data": { + "param2": "0x3d6cac9f032d82af63c2d077790354598cd194d920dadcf9996b", + "param3": [ + [ + "2215482091649323250149612409952168968001124083" + ], + [ + "3720428939728345178604370629051737310101916132" + ] + ], + "param6": "Moo é🚀o ééo🚀🚀 M🚀éo🚀🚀o🚀éé oéo🚀o🚀🚀oo éoMé🚀o 🚀éoéMM", + "param7": [ + "0xc8ce8e423057eb465576542851c8ae163f44bef2" + ] + }, + "encoded": "0xae9a402c7fe6b3d9bde74954593223cd4c7c61f3764929e780ca44432ba4edf88ebaa4befe0af4b10f9ff1d424dc9f2e501c9349db90511b8fc2ae5be855444f4c981d388229b9d3b092a114e1ab19340cd5ea397c66da5afc0bf366562778ba45cee17bca9a453477906b4710d48e03be64fbe1527a2a76f4c454afdec7e47587b1d2abb5f508f09df8e2d9dafbaa5dd87e71487b42b75e4b5a7d89feebfbc2", + "digest": "0xdbf3e30a06348c3a82df230158a8d3fe7be0948ba7e7e482eacdc44cae526ff9" + }, + { + "name": "random-127", + "domain": { + "name": "Moo é🚀", + "version": "42.13.26" + }, + "primaryType": "Struct13", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ], + "Struct13": [ + { + "name": "param2", + "type": "bytes" + }, + { + "name": "param3", + "type": "Struct8" + }, + { + "name": "param9", + "type": "address" + }, + { + "name": "param10", + "type": "bytes[2][]" + } + ], + "Struct8": [ + { + "name": "param4", + "type": "uint40" + }, + { + "name": "param5", + "type": "bytes" + }, + { + "name": "param6", + "type": "string[]" + } + ] + }, + "data": { + "param10": [ + [ + "0xe0a9f45f1a48a64f182328", + "0xd18e3c88f7b41cdb54f9a02dec1f9f2138b6c4f3718241bec86692e6912e4f3bdae4e15c968065966fc4c6" + ] + ], + "param2": "0xeed140f7e6f2069c90466326aca3d6c3af16", + "param3": { + "param4": "934183269602", + "param5": "0xa941fdd7a8fe8bfed7614a3a7ce12d949025684e32ab78ab621caa", + "param6": [] + }, + "param9": "0x219b81e0367f33c3face28f7ca0f98f42a3aad3f" + }, + "encoded": "0xec4d8bc63ac053b4abb7da4dcf5f9d853222e50f2cf3a7a70102a4ccf963484724c38815168dfc92aea0b45d4da4e474a0cccad6525ff2fa8584df0f4add65567a1e9576f0b9eccfba97fa5a64cec39eafe610e076674eeb749db12c47055f87000000000000000000000000219b81e0367f33c3face28f7ca0f98f42a3aad3f771f547647235bc1319baeaa2a6b4c3a394d0fee465d0d44fe7f3e6cc9cbf7d0", + "digest": "0x800e34308adad5c2fb5a176196e58c026d3e7e8a0485bc3f83f5f552bcf7e8aa" + }, + { + "name": "EIP712 example", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "primaryType": "Mail", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Mail": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Person" + }, + { + "name": "contents", + "type": "string" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallet", + "type": "address" + } + ] + }, + "data": { + "contents": "Hello, Bob!", + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + } + }, + "encoded": "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8", + "digest": "0xbe609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2" + } +] \ No newline at end of file diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index 72cad88ec2..2ae182279a 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -325,18 +325,17 @@ type Type struct { Type string `json:"type"` } +// isArray returns true if the type is a fixed or variable sized array. +// This method may return false positives, in case the Type is not a valid +// expression, e.g. "fooo[[[[". func (t *Type) isArray() bool { - return strings.HasSuffix(t.Type, "[]") + return strings.IndexByte(t.Type, '[') > 0 } -// typeName returns the canonical name of the type. If the type is 'Person[]', then +// typeName returns the canonical name of the type. If the type is 'Person[]' or 'Person[2]', then // this method returns 'Person' func (t *Type) typeName() string { - if strings.Contains(t.Type, "[") { - re := regexp.MustCompile(`\[\d*\]`) - return re.ReplaceAllString(t.Type, "") - } - return t.Type + return strings.Split(t.Type, "[")[0] } type Types map[string][]Type @@ -387,7 +386,7 @@ func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage // Dependencies returns an array of custom types ordered by their hierarchical reference tree func (typedData *TypedData) Dependencies(primaryType string, found []string) []string { - primaryType = strings.TrimSuffix(primaryType, "[]") + primaryType = strings.Split(primaryType, "[")[0] if slices.Contains(found, primaryType) { return found @@ -465,34 +464,11 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter encType := field.Type encValue := data[field.Name] if encType[len(encType)-1:] == "]" { - arrayValue, err := convertDataToSlice(encValue) + encodedData, err := typedData.encodeArrayValue(encValue, encType, depth) if err != nil { - return nil, dataMismatchError(encType, encValue) + return nil, err } - - arrayBuffer := bytes.Buffer{} - parsedType := strings.Split(encType, "[")[0] - for _, item := range arrayValue { - if typedData.Types[parsedType] != nil { - mapValue, ok := item.(map[string]interface{}) - if !ok { - return nil, dataMismatchError(parsedType, item) - } - encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) - if err != nil { - return nil, err - } - arrayBuffer.Write(crypto.Keccak256(encodedData)) - } else { - bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) - if err != nil { - return nil, err - } - arrayBuffer.Write(bytesValue) - } - } - - buffer.Write(crypto.Keccak256(arrayBuffer.Bytes())) + buffer.Write(encodedData) } else if typedData.Types[field.Type] != nil { mapValue, ok := encValue.(map[string]interface{}) if !ok { @@ -514,6 +490,46 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter return buffer.Bytes(), nil } +func (typedData *TypedData) encodeArrayValue(encValue interface{}, encType string, depth int) (hexutil.Bytes, error) { + arrayValue, err := convertDataToSlice(encValue) + if err != nil { + return nil, dataMismatchError(encType, encValue) + } + + arrayBuffer := new(bytes.Buffer) + parsedType := strings.Split(encType, "[")[0] + for _, item := range arrayValue { + if reflect.TypeOf(item).Kind() == reflect.Slice || + reflect.TypeOf(item).Kind() == reflect.Array { + encodedData, err := typedData.encodeArrayValue(item, parsedType, depth+1) + if err != nil { + return nil, err + } + arrayBuffer.Write(encodedData) + } else { + if typedData.Types[parsedType] != nil { + mapValue, ok := item.(map[string]interface{}) + if !ok { + return nil, dataMismatchError(parsedType, item) + } + encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) + if err != nil { + return nil, err + } + digest := crypto.Keccak256(encodedData) + arrayBuffer.Write(digest) + } else { + bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) + if err != nil { + return nil, err + } + arrayBuffer.Write(bytesValue) + } + } + } + return crypto.Keccak256(arrayBuffer.Bytes()), nil +} + // Attempt to parse bytes in different formats: byte array, hex string, hexutil.Bytes. func parseBytes(encType interface{}) ([]byte, bool) { // Handle array types. @@ -871,7 +887,8 @@ func init() { // Checks if the primitive value is valid func isPrimitiveTypeValid(primitiveType string) bool { - _, ok := validPrimitiveTypes[primitiveType] + input := strings.Split(primitiveType, "[")[0] + _, ok := validPrimitiveTypes[input] return ok } diff --git a/signer/core/apitypes/types_test.go b/signer/core/apitypes/types_test.go index 7ea32f298c..22bbeba19e 100644 --- a/signer/core/apitypes/types_test.go +++ b/signer/core/apitypes/types_test.go @@ -31,8 +31,9 @@ func TestIsPrimitive(t *testing.T) { t.Parallel() // Expected positives for i, tc := range []string{ - "int24", "int24[]", "uint88", "uint88[]", "uint", "uint[]", "int256", "int256[]", - "uint96", "uint96[]", "int96", "int96[]", "bytes17[]", "bytes17", + "int24", "int24[]", "int[]", "int[2]", "uint88", "uint88[]", "uint", "uint[]", "uint[2]", "int256", "int256[]", + "uint96", "uint96[]", "int96", "int96[]", "bytes17[]", "bytes17", "address[2]", "bool[4]", "string[5]", "bytes[2]", + "bytes32", "bytes32[]", "bytes32[4]", } { if !isPrimitiveTypeValid(tc) { t.Errorf("test %d: expected '%v' to be a valid primitive", i, tc) @@ -141,3 +142,94 @@ func TestBlobTxs(t *testing.T) { } t.Logf("tx %v", string(data)) } + +func TestType_IsArray(t *testing.T) { + t.Parallel() + // Expected positives + for i, tc := range []Type{ + { + Name: "type1", + Type: "int24[]", + }, + { + Name: "type2", + Type: "int24[2]", + }, + { + Name: "type3", + Type: "int24[2][2][2]", + }, + } { + if !tc.isArray() { + t.Errorf("test %d: expected '%v' to be an array", i, tc) + } + } + // Expected negatives + for i, tc := range []Type{ + { + Name: "type1", + Type: "int24", + }, + { + Name: "type2", + Type: "uint88", + }, + { + Name: "type3", + Type: "bytes32", + }, + } { + if tc.isArray() { + t.Errorf("test %d: expected '%v' to not be an array", i, tc) + } + } +} + +func TestType_TypeName(t *testing.T) { + t.Parallel() + + for i, tc := range []struct { + Input Type + Expected string + }{ + { + Input: Type{ + Name: "type1", + Type: "int24[]", + }, + Expected: "int24", + }, + { + Input: Type{ + Name: "type2", + Type: "int26[2][2][2]", + }, + Expected: "int26", + }, + { + Input: Type{ + Name: "type3", + Type: "int24", + }, + Expected: "int24", + }, + { + Input: Type{ + Name: "type4", + Type: "uint88", + }, + Expected: "uint88", + }, + { + Input: Type{ + Name: "type5", + Type: "bytes32[2]", + }, + Expected: "bytes32", + }, + } { + if tc.Input.typeName() != tc.Expected { + t.Errorf("test %d: expected typeName value of '%v' but got '%v'", i, tc.Expected, tc.Input) + } + } +} diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go index f8b3c9d86d..c62b513145 100644 --- a/signer/core/signed_data.go +++ b/signer/core/signed_data.go @@ -294,7 +294,7 @@ func typedDataRequest(data any) (*SignDataRequest, error) { func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { // Returns the address for the Account that was used to create the signature. // - // Note, this function is compatible with eth_sign and personal_sign. As such it recovers + // Note, this function is compatible with eth_sign. As such it recovers // the address of: // hash = keccak256("\x19Ethereum Signed Message:\n${message length}${message}") // addr = ecrecover(hash, signature) diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go index 4efc749b6f..74ea6f52a7 100644 --- a/tests/fuzzers/bls12381/bls12381_fuzz.go +++ b/tests/fuzzers/bls12381/bls12381_fuzz.go @@ -257,8 +257,12 @@ func fuzzCrossG1MultiExp(data []byte) int { cp.MultiExp(gnarkPoints, gnarkScalars, ecc.MultiExpConfig{}) // compare result - if !(bytes.Equal(cp.Marshal(), g1.ToBytes(&kp))) { - panic("G1 multi exponentiation mismatch gnark / geth ") + gnarkRes := cp.Marshal() + gethRes := g1.ToBytes(&kp) + if !bytes.Equal(gnarkRes, gethRes) { + msg := fmt.Sprintf("G1 multi exponentiation mismatch gnark/geth.\ngnark: %x\ngeth: %x\ninput: %x\n ", + gnarkRes, gethRes, data) + panic(msg) } return 1 @@ -283,15 +287,18 @@ func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, *blst.P1A if err != nil { panic(fmt.Sprintf("Could not marshal gnark.G1 -> geth.G1: %v", err)) } - if !bytes.Equal(g1.ToBytes(kp), cpBytes) { - panic("bytes(gnark.G1) != bytes(geth.G1)") + + gnarkRes := g1.ToBytes(kp) + if !bytes.Equal(gnarkRes, cpBytes) { + panic(fmt.Sprintf("bytes(gnark.G1) != bytes(geth.G1)\ngnark.G1: %x\ngeth.G1: %x\n", gnarkRes, cpBytes)) } // marshal gnark point -> blst point scalar := new(blst.Scalar).FromBEndian(common.LeftPadBytes(s.Bytes(), 32)) p1 := new(blst.P1Affine).From(scalar) - if !bytes.Equal(p1.Serialize(), cpBytes) { - panic("bytes(blst.G1) != bytes(geth.G1)") + blstRes := p1.Serialize() + if !bytes.Equal(blstRes, cpBytes) { + panic(fmt.Sprintf("bytes(blst.G1) != bytes(geth.G1)\nblst.G1: %x\ngeth.G1: %x\n", blstRes, cpBytes)) } return kp, cp, p1, nil @@ -316,8 +323,10 @@ func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, *blst.P2A if err != nil { panic(fmt.Sprintf("Could not marshal gnark.G2 -> geth.G2: %v", err)) } - if !bytes.Equal(g2.ToBytes(kp), cpBytes) { - panic("bytes(gnark.G2) != bytes(geth.G2)") + + gnarkRes := g2.ToBytes(kp) + if !bytes.Equal(gnarkRes, cpBytes) { + panic(fmt.Sprintf("bytes(gnark.G2) != bytes(geth.G2)\ngnark.G2: %x\ngeth.G2: %x\n", gnarkRes, cpBytes)) } // marshal gnark point -> blst point diff --git a/tests/state_test_util.go b/tests/state_test_util.go index e9a58694ed..af2cb63d94 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -196,7 +196,7 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error { // Run executes a specific subtest and verifies the post-state and logs func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) { - st, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme) + st, root, _, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme) // Invoke the callback at the end of function for further analysis. defer func() { postCheck(result, &st) @@ -228,10 +228,10 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo // RunNoVerify runs a specific subtest and returns the statedb and post-state root. // Remember to call state.Close after verifying the test result! -func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, err error) { +func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, gasUsed uint64, err error) { config, eips, err := GetChainConfig(subtest.Fork) if err != nil { - return st, common.Hash{}, UnsupportedForkError{subtest.Fork} + return st, common.Hash{}, 0, UnsupportedForkError{subtest.Fork} } vmconfig.ExtraEips = eips @@ -250,7 +250,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh post := t.json.Post[subtest.Fork][subtest.Index] msg, err := t.json.Tx.toMessage(post, baseFee) if err != nil { - return st, common.Hash{}, err + return st, common.Hash{}, 0, err } { // Blob transactions may be present after the Cancun fork. @@ -260,7 +260,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh // Here, we just do this shortcut smaller fix, since state tests do not // utilize those codepaths if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock { - return st, common.Hash{}, errors.New("blob gas exceeds maximum") + return st, common.Hash{}, 0, errors.New("blob gas exceeds maximum") } } @@ -269,10 +269,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh var ttx types.Transaction err := ttx.UnmarshalBinary(post.TxBytes) if err != nil { - return st, common.Hash{}, err + return st, common.Hash{}, 0, err } if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil { - return st, common.Hash{}, err + return st, common.Hash{}, 0, err } } @@ -308,6 +308,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh if tracer := evm.Config.Tracer; tracer != nil && tracer.OnTxEnd != nil { evm.Config.Tracer.OnTxEnd(nil, err) } + return st, common.Hash{}, 0, err } // Add 0-value mining reward. This only makes a difference in the cases // where @@ -322,7 +323,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh receipt := &types.Receipt{GasUsed: vmRet.UsedGas} tracer.OnTxEnd(receipt, nil) } - return st, root, err + return st, root, vmRet.UsedGas, nil } func (t *StateTest) gasLimit(subtest StateSubtest) uint64 { diff --git a/trie/trie_test.go b/trie/trie_test.go index 9b2530bdd4..423ed30fe8 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -819,6 +819,7 @@ type spongeDb struct { func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") } func (s *spongeDb) Delete(key []byte) error { panic("implement me") } +func (s *spongeDb) DeleteRange(start, end []byte) error { panic("implement me") } func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} } func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} } func (s *spongeDb) Stat() (string, error) { panic("implement me") } diff --git a/trie/trienode/proof.go b/trie/trienode/proof.go index d3075ecccf..01a07c05b0 100644 --- a/trie/trienode/proof.go +++ b/trie/trienode/proof.go @@ -69,6 +69,10 @@ func (db *ProofSet) Delete(key []byte) error { return nil } +func (db *ProofSet) DeleteRange(start, end []byte) error { + panic("not supported") +} + // Get returns a stored node func (db *ProofSet) Get(key []byte) ([]byte, error) { db.lock.RLock() diff --git a/trie/utils/verkle.go b/trie/utils/verkle.go index 12e02de9a4..4294f5e4be 100644 --- a/trie/utils/verkle.go +++ b/trie/utils/verkle.go @@ -156,10 +156,6 @@ func GetTreeKey(address []byte, treeIndex *uint256.Int, subIndex byte) []byte { func GetTreeKeyWithEvaluatedAddress(evaluated *verkle.Point, treeIndex *uint256.Int, subIndex byte) []byte { var poly [5]fr.Element - poly[0].SetZero() - poly[1].SetZero() - poly[2].SetZero() - // little-endian, 32-byte aligned treeIndex var index [32]byte for i := 0; i < len(treeIndex); i++ { @@ -204,10 +200,10 @@ func CodeChunkKey(address []byte, chunk *uint256.Int) []byte { return GetTreeKey(address, treeIndex, subIndex) } -func StorageIndex(bytes []byte) (*uint256.Int, byte) { +func StorageIndex(storageKey []byte) (*uint256.Int, byte) { // If the storage slot is in the header, we need to add the header offset. var key uint256.Int - key.SetBytes(bytes) + key.SetBytes(storageKey) if key.Cmp(codeStorageDelta) < 0 { // This addition is always safe; it can't ever overflow since pos